Echoes
Echoes

Reputation: 324

Convert & sort javascript array numerically using non-numeric key

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

Answers (4)

Nina Scholz
Nina Scholz

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

Nenad Vracar
Nenad Vracar

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

prasanth
prasanth

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

F.bernal
F.bernal

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

Related Questions