I want to pass an arithmetic expression as a string to Javascript and this string can contain any number of numerical arrays which will be dynamically populated.
For Eg: I need to evaluate the below expression
(pmPdcpVolDlDrb+pmPdcpVolDlSrb)/8/1024 , Where both pmPdcpVolDlDrb and pmPdcpVolDlSrb are numeric arrays
pmPdcpVolDlDrb =[ Array containing values for sensor pmPdcpVolDlDrb read from storage]
pmPdcpVolDlDrb =[ Array containing values for sensor pmPdcpVolDlDrb read from storage]
This expression can change and the number of variables involved can also change. I need a generalized way of handling it. I wrote the below code and it serves my purpose. I need to know if there is a better and standard way for the same.
// Expression for evaluation where pmPdcpVolDlDrb and pmPdcpVolDlSrb are arrays
expression="(pmPdcpVolDlDrb+pmPdcpVolDlSrb)/8/1024"
// Seperating out the variables from the expression. In my case variable names always start with pm
variables=expression.split(/\W+/).filter(word => word.includes("pm"));
array=[]
for(i=0;i<variables.length;i++){
array[i]= [1,2,3,4]// Replace with actual code to get the values of arrays to be computed
if (i===0)
expression=expression.replace(variables[i],"a")
else
expression=expression.replace(variables[i],"array["+i+"][i]")
}
resultantArray=array[0].map((a, i) => eval(expression))
Related
This question already has answers here:
Why does accessing an element in an object using an array as a key work?
(3 answers)
Closed 6 years ago.
Why does javascript evaluate the following as true, given that object foo has a valid property bar?
foo[[[["bar"]]]] === foo["bar"]
Based on operator precedence, I would think foo[[[["bar"]]]] is trying to access a property with the array [[["bar"]]] as the key, but why does that still "flatten down" to the same as foo["bar"]?
Colleagues of mine are saying javascript parsers have bracket simplifying which ignores the extra brackets. I don't think this is true since saving [[["foo"]]] to a variable test gives the same result:
> test = [[["bar"]]]
[Array[1]]
> foo["bar"] = 5
5
> foo[test]
5
What aspect of the language or parser is causing this behavior? Thanks!
JavaScript bracket notation accepts an expression, but it always converts the value of that expression to a string. Thus if you pass in an array, it will attempt to convert it to a string. In your case you are passing in an array [[["bar"]]], and [[["bar"]]].toString() === "bar".
If you are wondering why [[["bar"]]].toString() === "bar", it is because when an array arr is converted to a string implicitly it is like calling arr.join(','). That is each of its elements are converted to strings and then joined in a comma separated string. When the array only has one element, the string representation of the array is just the string representation of that one element. In your case your array ([[["bar"]]]) has one element: [["bar"]].
That array is converted to a string too, and since it is also a one element array, the string representation of it is the string representation of that single element: ["bar"].
["bar"] is also an array with one element, which is a string, so the string representation of ["bar"] is just "bar".
What this comes down to is: [[["bar"]]].toString() === "bar"
and foo[[[["bar"]]]] is the same as foo[[[["bar"]]].toString()].
You would also find that:
foo[[[[1]],[2]]] === foo["1,2"]
because: [[[1]],[2]].toString() === "1,2".
Let's see how foo[[[["bar"]]]] is evaluated, step-by step:
The outermost brackets in foo[...] denote a property
accessor. The expression foo[[[["bar"]]]] thus translates to
accessing a property of foo with name [[["bar"]]].
According to the ECMA standard, the abstract operation
ToPropertyKey(name) is then used to turn the name [[["bar"]]]
into a property key value:
A property key value is either an ECMAScript String value or a Symbol
value.
The name [[["bar"]]] is not of type Symbol and thus converted
into a string. An array is converted to a string by joining all its
string converted values:
[[["bar"]]].toString() === "bar"
Which finally means that our property key actually becomes "bar":
foo[[[["bar"]]]] === foo[[[["bar"]]].toString()] === foo["bar"]
I am trying to get the content of a data attribute with jquery but returned data is not what I had set.
With this simple example:
<div id="test" data-test="[1]"></div>
But $('#test').data('test') returns 1 instead of [1]
No problem using pure javascript.
View it online: https://jsfiddle.net/jojhm2nd/
jQuery's data is not an attribute accessor function. (This is a common mistake, easily made.) To just access the attribute, use attr.
$("#test").attr("data-test");
data does read data-* attributes, but only to initialize jQuery's data cache for that element. (And it never writes attributes.) It does a whole series of things including changing names (data-testing-one-two-three becomes testingOneTwoThree, for instance) and interpreting the values. In this case, it interprets the value as an array because it starts with [. When you show that array with alert, it's coerced to a string, and when you coerce an array to a string, that does an Array#join. If your attribute had been [1, 2], for instance, you'd've seen 1,2 as the result.
From the docs linked above:
Every attempt is made to convert the string to a JavaScript value (this includes booleans, numbers, objects, arrays, and null). A value is only converted to a number if doing so doesn't change the value's representation. For example, "1E02" and "100.000" are equivalent as numbers (numeric value 100) but converting them would alter their representation so they are left as strings. The string value "100" is converted to the number 100.
When the data attribute is an object (starts with '{') or array (starts with '[') then jQuery.parseJSON is used to parse the string; it must follow valid JSON syntax including quoted property names. If the value isn't parseable as a JavaScript value, it is left as a string.
jQuery does magic when you use the .data method.
From the jQuery website:
Every attempt is made to convert the string to a JavaScript value
(this includes booleans, numbers, objects, arrays, and null).
You can use the .attr method and do:
$('#test').attr('data-test');
How can I compare two math expressions in JavaScript?
For example "1 + x" and "x + 1".
There is a JavaScript Math parser but I couldn't find the logic to compare the parsed expressions:
https://github.com/silentmatt/js-expression-eval/blob/master/test.js
Are there other options?
Thanks
You will need a computer algebra system (CAS) to be able to truly test whether two expressions are equal. The only one I know of in JavaScript is javascript-cas, I'm not sure if this does what you need though. Other libraries like math.js and the mentioned js-expression-eval can parse expressions but miss to logic to understand whether two expressions are equal.
A pragmatic approach may be to compare the outcome of both expressions for a number of different values for x, and see if they have the same result. This will not always work though, for example 0/x+1 and x-x give the same result for every x but they aren't really equal.
If you need to know just the equality then you can do approximate comparison:
extract variable names from expressions
you have x+1 and 1+x so there is single variable x
genere pseudo random or grid set of values for them
use some spec point from -inf to +inf like x={ -1e-10, 1e-9, .... 1e+9,1e+10 }
add few randoms
parse each expression with current variable set
so take first x value
compute expressions value for it
if it is not the same expresions are not the same
try all cases from genered data set
if all pass then expressions are likely the same
if not (even if just in one pass) then expressions are not the same
I need to parse querystrings that contain both text and numbers. For example the following querystring:
?userID=12&team=Sales&quarter=Q1&count=2310
should be translated into the following JavaScript object:
{
userID:12, // not "12"
team:"Sales",
quarter:"Q1",
count:2310 // not "2310"
}
Currently I am doing it in two steps:
Parse the querystring
Go through all the parameters and identify which ones are numbers (either with a regex or an isNumber function !isNaN(parseFloat(n)) && isFinite(n)
This seems rather inefficient especially as most of my parameters are not numbers. Is there a better way?
do you know where are you going to use the specify value?
Because if you multiplying any string in number format like "3239" by 1 this will convert that string in number..
var example = 5 + (o.count*1) //o.count will be a number...
Two suggestions:
If you know which parameters are going to hold numbers, only do the conversion for those
The fastest way to convert strings to numbers as far as I know is to use the unary operator on them, as follows:
+(strVar)
Also multiplying by 1 is supposed to be fast AFAIK
After you parse the querystring you can convert those string representations of integer value to an actual integer like this:
var obj; // your object that the string is parsed into, with all values as strings.
for (var prop in obj) {
if (String(parseInt(obj[prop])) === obj[prop]) {
obj[prop] = parseInt(obj[prop]);
}
}
Is there a way to force .getRange().getValues() to return an int? Although only numbers exist in my range, it is returning them as strings. I would like to avoid using parseInt in every one of my statements or creating a separate array with converted values.
Or is that the only solution, to get the array and then parseInt the entire array in a loop?
you can do this easily using the unary '+' operator as follows:
First get your values from your spreadsheet using getValue() or getValues(). Suppose you get two such values, and store them in A = 1 and B = 2. You can force them to be recognized as numbers by using any math binary operator except for +, which concatenates strings, so A - B = -1, while A + B will return '12'.
You can force the variables to be numbers simply by using the + unary operator with any variable that might be interpreted as a string. For example, +A + +B will return the correct value of 3.
You can use parseInt() or Number()
example
var A='12';var B=5
A+B = 125
parseInt(A)+B = 17
Number(A)+B = 17
That said, getValues() is not supposed to return strings unless values have some space or other non-numeric characters in it... are these values entered manually or come as a result of some function ?
getValues() returns a 2D array of Objects - so these are Strings, Integers or Date objects depending on what these are formatted as in your spreadsheet.
Go back to your spreadsheet and see what the cells that have integer values are formatted as. Format them as integers and you should get back integers.