I'm trying to sort array using a function. But when the number is going to two digit sorting is not correct. Otherwise it's showing correct result. Please check the code.
this is the function:
var arr = [{name: "a1", value: 1},{name: "a3", value: 1},{name: "a4", value: 1},{name: "a2", value: 1}]; var arr2 = [{name: "a1", value: 1},{name: "a3", value: 1},{name: "a14", value: 1},{name: "a12", value: 1}]; var sort = function (prop, arr) { prop = prop.split('.'); var len = prop.length; arr.sort(function (a, b) { var i = 0; while( i < len ) { a = a[prop[i]]; b = b[prop[i]]; i++; } if (a < b) { return -1; } else if (a > b) { return 1; } else { return 0; } }); return arr; }; arr = sort('name', arr); arr2 = sort('name', arr2); console.log(arr); // it's correct console.log(arr2); // it's not correct
In this case I'm trying to sort the array based on value of name
.
You can use numeric collation with String#localeCompare
. It will avoid lexicographic sorting and give you proper numeric order:
var a = "10"; var b = "2"; console.log( //false - string "10" does not come after "2" because 1 < 2 "a > b:", a > b ); console.log( //-1 - `a` comes before `b` "a.localeCompare(b):", a.localeCompare(b) ); console.log( // 1 - `a` comes after `b` "a.localeCompare(b, undefined, {numeric: true}):", a.localeCompare(b, undefined, {numeric: true}) );
Note that this works for strings . If you also want to sort numbers, you have two easy options:
if
to check for what you're comparing and apply the .localeCompare
logic for strings and a different logic for numbers.Both would work but I personally prefer the first one, since it doesn't involve maintaining different cases. Thus using it in your solution gives the correct results:
var arr = [{name: "a1", value: 1},{name: "a3", value: 1},{name: "a4", value: 1},{name: "a2", value: 1}]; var arr2 = [{name: "a1", value: 1},{name: "a3", value: 1},{name: "a14", value: 1},{name: "a12", value: 1}]; var arr3 = [{name: "a", value: 3},{name: "a", value: 1},{name: "a", value: 14},{name: "a", value: 12}]; var sort = function (prop, arr) { prop = prop.split('.'); var len = prop.length; arr.sort(function (a, b) {var i = 0; while( i < len ) { a = a[prop[i]]; b = b[prop[i]]; i++; } //cast to string a = String(a); b = String(b); return a.localeCompare(b, undefined, {numeric: true}) }); return arr; }; arr = sort('name', arr); arr2 = sort('name', arr2); console.log(arr); // it's correct console.log(arr2); // it's correct arr3 = sort('value', arr3); console.log(arr3); // it's correct
You need to split the alphabets and digits and then compare them
var arr = [{name: "a1", value: 1},{name: "a3", value: 1},{name: "a4", value: 1},{name: "a2", value: 1}]; var arr2 = [{name: "a1", value: 1},{name: "a3", value: 1},{name: "a14", value: 1},{name: "a12", value: 1}]; var arr3 = [{name: 1, value: 1},{name: 11, value: 1},{name: 14, value: 1},{name: 12, value: 1}]; var sort = function (prop, arr) { prop = prop.split('.'); var len = prop.length; arr.sort(function (a, b) { var i = 0; while( i < len ) { a = a[prop[i]]; b = b[prop[i]]; i++; } let [key1,digit1] = (""+a).split(/(?<=[az])(?=\d)/) let [key2,digit2] = (""+b).split(/(?<=[az])(?=\d)/) return (key1 - key2) || (+digit1 - +digit2) }); return arr; }; arr = sort('name', arr); arr2 = sort('name', arr2); arr3 = sort('name', arr3) console.log(arr); // it's correct console.log(arr2); // it's not correct console.log(arr3);
Name property is of type string that is why sort is performed in lexicographical order(ie alphabetical order). You would need to parse name field to sort by number inside name.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.