Reputation: 324
I have a JS array in following structure:
Array(
[0] => Array(
reference : "8926"
name : "xyz1"
id_product : "78"
)
[1] => Array(
reference : "11588"
name : "xyz2"
id_product : "21"
)
[2] => Array(
reference : "119"
name : "xyz3"
id_product : "135"
)
)
I needed to sort this array using the reference
key, I have done it using multisort function;
But the problem is : even though reference
is numeric but in the array structure it is defined as string and hence instead of sorting like:
119, 8926, 11588
it is sorting it like 11588 119 8926
, i.e., like string.
I cannot re-structure the array because I receive it through an API, is there anyway to sort it numerically without having to recreate it in numeric data type separately (because I have to pass the array forward in same format & hence double-conversion will make the script hectic)?
PS - Current sorting (non-numeric) is done using this function.
Upvotes: 0
Views: 282
Reputation: 386624
I suggest to upgrade the used library a bit for using it with numerical values.
var x = is_numeric ? +a[columns[index]] : a[columns[index]].toLowerCase(); // <-- this line
var y = is_numeric ? +b[columns[index]] : b[columns[index]].toLowerCase(); // <-- this line
// ^ add this unary plus to get a numerical value istead of a string
var helper = {
arr: {
/**
* Function to sort multidimensional array
*
* param {array} [arr] Source array
* param {array} [columns] List of columns to sort
* param {array} [order_by] List of directions (ASC, DESC)
* returns {array}
*/
multisort: function (arr, columns, order_by) {
if (typeof columns == 'undefined') {
columns = []
for (x = 0; x < arr[0].length; x++) {
columns.push(x);
}
}
if (typeof order_by == 'undefined') {
order_by = []
for (x = 0; x < arr[0].length; x++) {
order_by.push('ASC');
}
}
function multisort_recursive(a, b, columns, order_by, index) {
var direction = order_by[index] == 'DESC' ? 1 : 0;
var is_numeric = !isNaN(a[columns[index]] - b[columns[index]]);
var x = is_numeric ? +a[columns[index]] : a[columns[index]].toLowerCase(); // add plus
var y = is_numeric ? +b[columns[index]] : b[columns[index]].toLowerCase(); // add plus
// ^ add this unary plus to get a numerical value istead of a string
if (!is_numeric) {
x = helper.string.to_ascii(a[columns[index]].toLowerCase(), -1),
y = helper.string.to_ascii(b[columns[index]].toLowerCase(), -1);
}
if (x < y) {
return direction == 0 ? -1 : 1;
}
if (x == y) {
return columns.length - 1 > index ? multisort_recursive(a, b, columns, order_by, index + 1) : 0;
}
return direction == 0 ? 1 : -1;
}
return arr.sort(function (a, b) {
return multisort_recursive(a, b, columns, order_by, 0);
});
}
}
};
var array = [{ reference: "8926", name: "xyz1", id_product: "78" }, { reference: "11588", name: "xyz2", id_product: "21" }, { reference: "119", name: "xyz3", id_product: "135" }];
console.log(helper.arr.multisort(array, ['reference'], ['ASC']));
console.log(helper.arr.multisort(array, ['reference'], ['DESC']));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 122047
You can convert both parameters from string to number using unary plus +
operator inside sort()
function.
var data = [{"reference":"8926","name":"xyz1","id_product":"78"},{"reference":"11588","name":"xyz2","id_product":"21"},{"reference":"119","name":"xyz3","id_product":"135"}]
data.sort((a, b) => +a.reference - +b.reference);
console.log(data)
Upvotes: 4
Reputation: 22500
Try with parseFloat
its convert the string to number.Then sorting with ASC
order
var Arr = [{"reference":"8926","name":"xyz1","id_product":"78"},{"reference":"11588","name":"xyz2","id_product":"21"},{"reference":"119","name":"xyz3","id_product":"135"}]
Arr.sort((a, b) => parseFloat(a.reference) - parseFloat(b.reference));
console.log(Arr)
Upvotes: 0
Reputation: 2684
Try this:
let a = new Array(
{
reference : "8926",
name : "xyz1",
id_product : "78"
},
{
reference : "11588",
name : "xyz2",
id_product : "21"
},
{
reference : "119",
name : "xyz3",
id_product : "135"
}
);
a.sort((a, b) => {
return Number(a.reference) - Number(b.reference);
});
Upvotes: 1