More elegant secondary sorting for arrays

I need to sort by array, and if the two elements are equal, then I need to do a secondary sort on a different key inside these elements. Taking a look at the Mozilla Developer Network docs for array.sort , there is a good piece of code below to handle the first view. I liked it because it was concise and shows how you can write powerful JS.

Here is what I tried based on code from MDN. This correctly makes the first appearance.

// the array to be sorted
var list = [{name:'Delta', ref: 456}, {name:'Delta', ref: 123}, {name:'alpha', ref: 789}, {name:'CHARLIE', ref: 012}, {name:'bravo', ref: 345}];

// temporary array holds objects with position and sort-value
var mapped = list.map(function (el, i) {
  return {
    index: i,
    value: el.name.toLowerCase(),
    secondaryValue: el.ref
  };
});

// sorting the mapped array containing the reduced values
mapped.sort(function (a, b) {
  return +(a.value > b.value) || +(a.value === b.value) - 1;
});

// container for the resulting order
var result = mapped.map(function (el) {
  return list[el.index];
});

console.log(list);
console.log(result);

Now I know that I can change a comparison function like this to fulfill the secondary sort requirement:

// sorting the mapped array containing the reduced values
mapped.sort(function (a, b) {
  if (a.value === b.value){
    return +(a.secondaryValue > b.secondaryValue) || +(a.secondaryValue === b.secondaryValue) - 1;
  }

  return +(a.value > b.value) || - 1;
});

But for me it loses some of the charm return +(a.value > b.value) || +(a.value === b.value) - 1;- it's pretty cool, in my opinion.

: ?

: Pure JS. ES5 , , ES6 .

+4
3

||, 0, , .

mapped.sort(function (a, b) {
    return (+(a.value > b.value) || +(a.value === b.value) - 1) ||
        (+(a.secondaryValue > b.secondaryValue) || +(a.secondaryValue === b.secondaryValue) - 1);
});

var list = [{name:'Delta', ref: 456}, {name:'Delta', ref: 123}, {name:'alpha', ref: 789}, {name:'CHARLIE', ref: 12}, {name:'bravo', ref: 345}],
    mapped = list.map(function (el, i) {
        return {
            index: i,
            value: el.name.toLowerCase(),
            secondaryValue: el.ref
        };
    });

mapped.sort(function (a, b) {
    return a.value.localeCompare(b.value) || a.secondaryValue - b.secondaryValue;
});

var result = mapped.map(function (el) {
    return list[el.index];
});

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Hide result
+3

, :

?

, , , .


Array.prototype.sort, , , . , :

a = [2, 1, 3];
a.sort(function (a, b) {
    return b - a;
});

, sort, , .

lodash, , , , multisort , , :

multisort = (function () {
// or for commonjs
// module.exports = (function () {
    function slice(arr) {
        return Array.prototype.slice.call(arr);
    }

    // multisort(arr, [fn1], [fn2] ...)
    return function multisort(arr) {
        var args;

        //copy the arguments into a new array
        args = slice(arguments);

        //copy the array to a new array and sort the new array    
        return slice(arr).sort(function (a, b) {
            var i,
                fn,
                res;

            //iterate over the sort callbacks
            for (i = 1; i < args.length; i++) {
                fn = args[i];
                //call the sort callback,
                //this version doesn't do anything special with setting a context
                res = fn(a, b);
                //if the sort value is anything other than 0, return it
                //otherwise fall to the next sort function
                if (res) {
                    return res;
                }
            }
            return 0;
        });
    }
}());

:

mapped = multisort(mapped, function (a, b) {
    return +(a.value > b.value) || +(a.value === b.value) - 1;
}, function (a, b) {
    return +(a.secondaryValue > b.secondaryValue) || +(a.secondaryValue === b.secondaryValue) - 1;
});

, , .

0

?

function thenby(comparer, func) {
    return function (a, b) {
        var intermidiate = comparer(a, b);
        if (intermidiate)
          return intermidiate;
        else
          return func(a, b)
    };
}

var comparer = function (a, b) {
    return +(a.value > b.value) || +(a.value === b.value) - 1;
};

comparer = thenby(comparer, function (a, b) {
    return +(a.secondaryValue > b.secondaryValue) || +(a.secondaryValue === b.secondaryValue) - 1;
});

mapped.sort(comparer);
0
source

Source: https://habr.com/ru/post/1618485/


All Articles