Javascript sorting array of equal values in chrome - javascript

I have this sorting function, but which i use to sort a table, i can sort by dates (which i have removed for simplicity) and strings, but intergers are acting wierd, a common case is that all values could be 0, which will give the array
[0,0,0,0]
this works perfectly in firefox but not in chrome, it changes the order of the rows in my table although they are equal, i have even followed the ECMA standards. Why do chrome change the order anyway? I have also tried using
return (ascending_order ? a - b : b - a)
But with the same result as my more general approach to work with different data types
arr.sort(function(a, b){
var onlydigitsRegex = new RegExp("\d+","g");
if (a.match(onlydigitsRegex) && b.match(onlydigitsRegex)) {
a = parseInt(a);
b = parseInt(b);
} else {
a = a.toLowerCase();
b = b.toLowerCase();
}
return (a === b) ? 0 : (ascending_order ? ((a > b) ? 1 : -1) : ((a < b)? 1 : -1));
});

Related

Why is the browser sorting in the following way

I have following function:
var sortString = function (a, b) {
a = a.toLowerCase();
b = b.toLowerCase();
if (a < b) return 1;
if (a > b) return -1;
return 0;
}
and I have following two strings:
x = ["B1C3N_EUR_DFAK_ALL_3M_ALL","B1C3N_EUR_BPP_BCO_3M"];
When I run the above function on this array. I expect "B1C3N_EUR_BPP_BCO_3M" to be at index 0 whereas browser returns it in the reverse order. I have checked both on Chrome and IE. Why is it so??
Do I need to replace "-" with some other values. Is there any way I can do it without replacing.
You return the wrong value for smaller and greater value in the callback for Array#sort.
if (a < b) return 1;
// ^ should be -1, because a is smaller than b
if (a > b) return -1;
// ^^ should be 1, because a is greater than b
For a more concise style, you could use String#localeCompare, which test the given strings and returns a value in the wanted range.

Sort numbers with slashes in knockout js or javascript

I have series of numbers as strings I want to sort.
for example
4604158/1/7,4604181/1/2,4604158/1/8,4604182/1/2,4604181/1/3, 4604282/1/2 etc.
how can I achieve this with knockout js or even with simple javascript?
I am able to sort only numbers (without slashes) with the following code :
myObservableArray.sort(function (item1, piece2) {
return item1.stringWithSlashes < item2.stringWithSlashes ? -1 : (item1.stringWithSlashes > item2.stringWithSlashes ? 1 : 0);
});
You could split the strings and sort then with the first part, then the second and if equal by the third part.
var array = ['4604158/1/7', '4604181/1/2', '4604158/1/8', '4604182/1/2', '4604181/1/3', '4604282/1/2'];
array.sort(function (a, b) {
var aa = a.split('/'),
bb = b.split('/');
return aa[0] - bb[0] || aa[1] - bb[1] || aa[2] - bb[2];
});
console.log(array);
This is a dynamic way to check with any separator and any length of separated result array.
var array = ['4604158/1/7', '4604181/1/2', '4604158/1/8', '4604182/1/2', '4604181/1/3', '4604282/1/2'];
var separator = '/';
array.sort(function(a, b) {
b = b.split(separator);
return a.split(separator)
.some((v, i) => (+v > +b[i]));
})
console.log(array);

Sorting an array based on alphabets?

I need to sort an array based on Alphabets. I have tried sort() method of javascript, but it doesn't work since my array consists of numbers, lowercase letters and uppercase letters. Can anybody please help me out with this? Thanks
For e.g my array is:
[
"#Basil",
"#SuperAdmin",
"#Supreme",
"#Test10",
"#Test3",
"#Test4",
"#Test5",
"#Test6",
"#Test7",
"#Test8",
"#Test9",
"#a",
"#aadfg",
"#abc",
"#abc1",
"#abc2",
"#abc5",
"#abcd",
"#abin",
"#akrant",
"#ankur",
"#arsdarsd",
"#asdd",
"#ashaa",
"#aviral",
"#ayush.kansal",
"#chris",
"#dgji",
"#dheeraj",
"#dsfdsf",
"#dualworld",
"#errry",
"#george",
"#ggh",
"#gjhggjghj"
]
a.sort(function(a, b) {
var textA = a.toUpperCase();
var textB = b.toUpperCase();
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
});
This should work (jsFiddle)
function alphabetical(a, b){
var c = a.toLowerCase();
var d = b.toLowerCase();
if (c < d){
return -1;
}else if (c > d){
return 1;
}else{
return 0;
}
}
yourArray.sort(alphabetical);
To sort an array by a key function applied to an element (toUpperCase here), Schwartzian transform, aka "decorate-sort-undecorate" is your technique of choice:
cmp = function(x, y) { return x > y ? 1 : x < y ? -1 : 0 }
sorted = array.map(function(x) {
return [x.toUpperCase(), x]
}).sort(function(x, y) {
return cmp(x[0], y[0])
}).map(function(x) {
return x[1]
})
The major advantage of this approach is that the key function is called exactly once for each element, which can matter when the key is heavy or has side effects.
I realize that you're looking for a simple answer right now, but this might be something for you to consider learning in the future.

alphanumeric zero padding in dataTables?

I feel like this has a "duh" answer, but
I am using the jQuery Plugin DataTables.net to display a json Google Spreadsheet. You can see it in action here: http://jsfiddle.net/ukoku/jEqu2/2/
I would like to sort the rows by the Location column, which reads in A1, B2 format, like chess. With numbers I know I'd need zero padding, but I have no idea how to add zeros to alphanumeric data, nor do I have any clue how to do it with DataTables instead of regular string.
EDIT: Sorry, I wasn't clear. The place where I thought zeros needed to be added was between the alphabetic character and the number in the Location slot. Currently, Q9 sorts as being after Q14, for example. I need it to sort first by alpha (Ax, Bx), then within that sort as numbers. Normally when I've had 1 show up as higher than 10, it's because I needed to padleft with zeros to get 001 and 010. But I'm not sure how to stick zeros between the numbers for Q009 and Q014, etc., or it that's even the proper solution.
Eventually, the goal is to customize the CSS to display rows with the same location in groups. I honestly have no idea if this is possible either, but since I can't even get the data sorted....
Is this on the right track of what you're after? http://jsfiddle.net/rMUWD/
Here's another way to do it:
var compare = function(a, b) {
return a > b ? 1 : a === b ? 0 : -1;
},
compareAlphanumeric = function (a, b) {
alpha = compare(a.alpha, b.alpha);
numeric = compare(a.numeric, b.numeric);
return (alpha === 1 | (alpha === 0 && numeric === 1)) ? 1 : (alpha === 0 && numeric === 0) ? 0 : -1;
};
jQuery.fn.dataTableExt.oSort['alphaNumeric-asc'] = function(a, b) {
var r = /^([A-Za-z]+)([0-9]+$)/,
a = {
"alpha": a.split(r)[1],
"numeric": parseInt(a.split(r)[2], 10)
},
b = {
"alpha": b.split(r)[1],
"numeric": parseInt(b.split(r)[2], 10)
};
return compareAlphanumeric(a, b);
};
jQuery.fn.dataTableExt.oSort['alphaNumeric-desc'] = function(a, b) {
var r = /^([A-Za-z]+)([0-9]+$)/,
a = {
"alpha": a.split(r)[1],
"numeric": parseInt(a.split(r)[2], 10)
},
b = {
"alpha": b.split(r)[1],
"numeric": parseInt(b.split(r)[2], 10)
};
return compareAlphanumeric(b, a); //reverse a and b for desc
};
Working fiddle here: http://jsfiddle.net/jEqu2/3/
The compare function is your basic comparison function. compareAlphanumeric returns 1, 0, or -1 based on the following truth table:
/*
Alpha Numeric Result
-1 -1 -1
-1 0 -1
-1 1 -1
0 -1 -1
0 0 0
0 1 1
1 -1 1
1 0 1
1 1 1
*/
The bulk of the actual work is done in the oSort functions:
//First declare a RegExp to split the location into an array of [letter, number]
var r = /^([A-Za-z]+)([0-9]+$)/,
//convert the passed "a" parameter to an object containing its letter and number,
//and parse the number portion to an actual number instead of its string representation.
a = {
"alpha": a.split(r)[1],
"numeric": parseInt(a.split(r)[2], 10)
},
//do the same for b
b = {
"alpha": b.split(r)[1],
"numeric": parseInt(b.split(r)[2], 10)
};
//return the alphanumeric comparison
return compareAlphanumeric(a, b);
and in the descending oSort, we only have to switch the order of the parameters passed to compareAlphanumeric.

Optimizing this double comparison result for sorting in javascript

Usually while sorting you do:
if (x < y) return -1
else if (x > y) return 1
else return 0
or
return ((x > y) ? 1 : ((x < y)) ? -1 : 0))
Two comparisons for what seems can be accomplished with only one. In assembly all you have to do is subtract both to a register, check if is negative, check if is zero. The problem is in javascript if we were to subtract:
var sub = (x - y);
return (sub == 0 ? 0 : ((sub < 0) ? -1 : 1))
This would end up with even more code to be executed.
So, some questions:
Is there a way of simplifying or speedying this in javascript?
Can compiled javascript interpretors like chrome's optimize this kind of comparison?
What about other languages?
In Javascript, sort does not have to return -1, 0 or 1. It can return any number. This means that you only need to subtract one number from the other to compare them.
The MDC docs for Array.sort suggest this implementation:
function compareNumbers(a, b)
{
return a - b;
}
var nums = [34, 56, 1, 42, 63];
nums.sort(compareNumbers);
// [1, 34, 42, 56, 63]
Usually the sort algorithm is not looking specifically for -1 or +1, just <0 or >0.
The comparison function in this case could be as simple as
return x - y ;
sorting alphabetically can be done with array.sort(), but if you want a case insensitive sort you do need to test if the strings are the same, or if one is greater or less than the other.
array.sort(function(a,b){
a=a.toLowerCase();
b=b.toLowerCase();
if(a==b) return 0;
return a>b? 1:-1;
}
Worrying about an extra comparison is beside the point here, the conversion toLowerCase is what eats up cycles. SO don't use toLowerCase unless you need it.
Numbers, as has been shown, are simple-
array.sort(function(a,b){ return a-b});

Categories