This question already has an answer here:
Comparing numbers of type string
(1 answer)
Closed 4 years ago.
After ajax query I have the next numbers:
var a = "5.20";
var b = "7.20";
var c = "11.20";
I have noticed that if compare numbers above 10.00 the condition is false. I do not understand why this happens
if (b > a) console.log("higher"); // true
if (c > b) console.log("higher"); // not true
I have solved the problem with next code (it should also work parseFloat)
if ((+c) > (+b)) console.log("higher"); // true
"5" > "10" for the same reason that "m" > "ba". Strings are compared alphabetically (even if they contain digits) - or rather lexicographically.
The variables are string type. Not integers.
typeof("5.20"); // OUTPUT: "string"
Remove the quotation marks:
var a = 5.20;
var b = 7.20;
var c = 11.20;
if (b > a) console.log("higher"); // true
if (c > b) console.log("higher"); // also true
Example: https://www.w3schools.com/js/js_comparisons.asp
You are comparing two strings alphabetically. If you remove the quotes where you create the variables then you will have numbers and your code will work.
var a = 5.20;
var b = 7.20;
var c = 11.20;
Related
This question already has answers here:
How to compare an array of strings in Javascript?
(6 answers)
Closed 3 months ago.
I have a little problem to solve. I want to compare two texts if they are the same.
let currentValue = "24960307.W 25880305.W 24880208.W 25650156.W"
let newValue = "24880208.W 24960307.W 25650156.W 25880305.W"
// is the same text just diferent order
// when i did includes
let x = currentValue.includes(value);
console.log(x);
//response in console
false
I tried with includes and localeCompare but still show that text is different.
A quick solution to normalize order is to split, sort, rejoin, then compare. This avoids any fancy parsing.
let currentValue = "24960307.W 25880305.W 24880208.W 25650156.W"
let newValue = "25880305.W 24880208.W 25650156.W 24960307.W"
const a = currentValue.split(' ').sort().join(' ')
const b = newValue.split(' ').sort().join(' ')
console.log(a === b)
let x = a.localeCompare(b) === 0
console.log(x);
This question already has answers here:
What exactly is Type Coercion in Javascript?
(9 answers)
Closed 2 years ago.
I have array, by which at some point am mapping the array and calculating sum and percentages. So while implementing the logic i saw that, when i use '*' directly its working but when i use '+' it just adds the two string
For example:
const a = '100';
const b = '10';
const c = a * b;
const d = a + b;
console.log(d)
When i checked the d , it gives '10010' and when c it gives '1000' ! How is this ?
But when i use parseInt(a) + parseInt(b) it works perfectly with 110 as output
In JavaScript there are no primitive datatypes like int, float etc. There are only variables which can be initialized with everything you need. For your example
const a = 100;
const b = 10;
const c = a * b;
const d = a + b;
console.log(d);
should work perfectly, because I removed ''. With '' the constant thinks it is a string provided. Without '' there are just the numbers saved in the constants. Also + doesn't work in your example, because as I said the constants think the numbers are a string due to ''. So it just puts this two "strings" together and not summing them up.
I am wondering why the following works:
oldversion = "1.3.52";
newversion = "1.3.54";
if (newversion > oldversion) {
console.log('test');
}
but this does not:
if (1.3.54 > 1.3.52) {
console.log('test');
}
I know that the last example won't work because they are not actual numbers. But I am trying to find out what JavaScript is doing when it encounters a string with a number in it.
This is what I found on W3Schools' JavaScript Comparison and Logical Operators page:
When comparing a string with a number, JavaScript will convert the
string to a number when doing the comparison.
So how come it converts the string to a number and suddenly I am not getting an Uncaught SyntaxError: Unexpected number anymore?
You could use a function which iterates the segments.
function checkVersion(a, b) {
var aa = a.split('.').map(Number),
bb = b.split('.').map(Number),
i,
r = 0,
l = Math.max(aa.length, bb.length);
for (i = 0; !r && i < l; i++) {
r = (aa[i] || 0) - (bb[i] || 0);
}
return r;
}
var oldversion = "1.3.52",
newversion = "1.3.54";
if (checkVersion(newversion, oldversion) > 0) {
console.log('test');
}
As mentioned in the comments, it's actually doing a string compare and not trying to turn anything into numbers.
You can verify this by trying:
var a = "a";
var b = "b";
console.log(a>b) // gives false
var a = "a";
var b = "b";
console.log(b>a) // gives true
As you say, when you compare a number and a string, the string gets transformed into a number. However, if the string contains an invalid number, the result will be NaN. This is funny due to the fact that:
NaN > 15 === false
NaN < 15 === false
So:
"1.3.52" > 1.4 === false
"1.3.52" < 1.4 === false
Obviously (and as you said in your post), comparing 1.3.52 with 1.3.54 will throw an exception because they're not valid numbers.
Why "1.3.52" is interpreted bigger than '1.12.10'?
Strings are compared using Unicode code point order. For example, "Banana" comes before "cherry". "9" is bigger than "80", but because "80" comes before "9" in Unicode order. Thus, "1.3.52" is interpreted as bigger than '1.12.10'.
An easy way to find out order between strings and not getting tricked is using sort. For instance, ["1.3.52", "1.12.10", "1.11.0.0.0"].sort()
#Nina's solution should be the accepted answer, as it will be easier to understand I think. But anyway..
function versionGreaterEqual(newversion, oldversion) {
var ov = oldversion.split('.').map(Number), //credit Nina :)
nv = newversion.split('.').map(Number);
return nv.reduce(function (a,b,i){
return a+=b>=ov[i];
},0)===nv.length;
}
console.log(versionGreaterEqual("1.3.54", "1.3.52")); //true
console.log(versionGreaterEqual("1.3.54", "1.13.52")); //false
This question already has answers here:
How to perform case-insensitive sorting array of string in JavaScript?
(15 answers)
Closed 8 years ago.
Say if I had a Javascript array as following and I sorted the array before printing it to console
var f = ["Salil", "Sam", "Anil", "John", "ajay", "Baba"];
f.sort();
console.log(f);
It prints as follows
Anil,Baba,John,Salil,Sameer,ajay
Why does ajay prints last, how does the case of the first letter plays a role?
thanks,
Salil
The lower-case letters come after the upper-case letters in Unicode (in the base code page at least).
You can sort so that you pay no attention to case:
f.sort(function(w1, w2) {
w1 = w1.toLowerCase(); w2 = w2.toLowerCase();
return w1 < w2 ? -1 : w2 < w1 ? 1 : 0;
}
More complicated collations require more complicated comparison routines. The function you pass to .sort() should take two arguments, those being two members of the array to be compared. It's pretty important that your comparator function always returns the same answer for any two strings (in either order!), or else things can get weird.
Because lowercase letters come after uppercase letters.
To enable caseless sorting, try this:
f.sort(function(a,b) {return a.toLowerCase() < b.toLowerCase() ? -1 : 1;});
Here is an example in long form to make it a bit clearer with the whole if/else if/else chain for returning -1/1/0 from the sort comparison:
var caseInsensitiveComparator = function(a, b) {
var _a = a.toLowerCase(),
_b = b.toLowerCase();
if (_a < _b) {
return -1;
} else if (_b < _a) {
return 1;
} else {
return 0;
}
};
var f = ["Salil", "Sam", "Anil", "John", "ajay", "Baba"];
f.sort(caseInsensitiveComparator);
console.log(f);
> ["ajay", "Anil", "Baba", "John", "Salil", "Sam"]
The Mozilla Developer Network page on Array.prototype.sort has an explanation on how sort works.
I have this below loop in my function
I see it loop through if x is <10 but if it is greater than 10 it fails even though the condition of y < x satisfies
function insert(x,y) {
for (var shift = y; shift < x; shift++) {
//get into loop for insert (9,2) but not for insert(10,2)
}
}
This is the actual function, I am trying to visualize a insert before scenario using rapheal.js it works for insertBeforeTo(9,2) but when i try insertBeforeTo(10,2) it do not get into the loop.
function insertBeforeTo(whichElementI, insertBeforeI) {
var twhichElement = blocks[whichElementI];
blocks[whichElementI].animate({ x: blocks[insertBeforeI].attr('x') }, 1000, ">");
var shiftplusone = insertBeforeI;
for (var shift = insertBeforeI; shift < whichElementI; shift++) {
++shiftplusone;
blocks[shift].animate({ x: blocks[shiftplusone].attr('x') }, 1000, ">");// check value actually changes
}
}
Down voters: mind explaining?
Issue found: while debugging I see whichElementI and insertBeforeI values in ' '. So I assume It takes it as a string and as nnnnn and paxdiablo rightly pointed out, it takes as string instead of int so It worked for whichElementI = 9 and insertBeforeI = 2 and not whichElementI= 10 ,insertBeforeI=2.
So I used unary plus operator like +whichElementI, +insertBeforeI which fixes the issue.
Thanks
I'm guessing you are inadvertantly calling your function with string values rather than number values, that is with
insert("9", "2")
insert("10", "2")
...rather than
insert(9, 2)
insert(10, 2)
If you are getting your values from html element attributes, for example, they'll be strings.
With strings, "2" < "9" is true, but "2" < "10" is false - it does a lexicographic (dictionary) order comparison, not a numeric comparison.
If you want your function to work either way then you can change it to convert strings to numbers (I prefer to use the unary plus operator for that purpose):
function insert(x,y) {
x = +x;
y = +y;
for (var shift = y; shift < x; shift++) {
//get into loop for insert (9,2) but not for insert(10,2)
}
}
I don't know what the types of whichElementI and insertBeforeI are, but convert them to numeric by *1. That should help keep some of the arithmetic in check. Might also want to check if(isNaN(some_var)==false){...} as a sanity check.
function insertBeforeTo(whichElementI, insertBeforeI) {
var twhichElement = blocks[whichElementI];
blocks[whichElementI].animate({ x: blocks[insertBeforeI].attr('x') }, 1000, ">");
var shiftplusone = insertBeforeI*1;
for (var shift = insertBeforeI*1; shift < whichElementI*1; shift++) {
++shiftplusone;
blocks[shift].animate({ x: blocks[shiftplusone].attr('x') }, 1000, ">");// check x value actually changes
}
}
You should first check what data types you're passing in to the function.
For example, all of these produce output:
insert ( 10, 2)
insert ( 9, 2)
insert ( '9', '2')
but the following does not:
insert ( '10', '2')
That's because the string '10' is actually less than the string '2'. By that, I mean that a string is not treated numerically when sorting or comparing, rather each character is compared individually, leading to things like the first twelve numbers being sequenced as:
1
10
11
12
2
3
4
5
6
7
8
9
You can see this in action with the following code (at one of the many on-line JS runners):
function insert(x,y) {
for (var shift = y; shift < x; shift++) {
//get into loop for insert (9,2) but not for insert(10,2)
document.write('x');
}
}
document.write('<br>10,2 as string: '); insert ('10','2');
document.write('<br>9,2 as string: '); insert ( '9','2');
document.write('<br>9,2 as num: '); insert ( 9, 2);
document.write('<br>10,2 as num: '); insert ( 10, 2);
which outputs:
10,2 as string:
9,2 as string: xxxxxxx
9,2 as num: xxxxxxx
10,2 as num: xxxxxxxx
If you have a string that you want treated as a number, parseInt() is one way to go, something like:
var str42 = '42';
var num42 = parseInt (str42, 10);