Подтвердить что ты не робот

Сортировка элементов в массиве более чем одним полем с lodash

Как я могу отсортировать массив объектов более чем одним полем с помощью lodash. Итак, для такого массива:

[
  {a: 'a', b: 2},
  {a: 'a', b: 1},
  {a: 'b', b: 5},
  {a: 'a', b: 3},
]

Я бы ожидал этого результата

[
  {a: 'a', b: 1},
  {a: 'a', b: 2},
  {a: 'a', b: 3},
  {a: 'b', b: 5},
]
4b9b3361

Ответ 1

Это намного проще в текущей версии lodash (2.4.1). Вы можете просто сделать это:

var data = [
    {a: 'a', b: 2},
    {a: 'a', b: 1},
    {a: 'b', b: 5},
    {a: 'a', b: 3},
];

data = _.sortBy(data, ["a", "b"]);  //key point: Passing in an array of key names

_.map(data, function(element) {console.log(element.a + " " + element.b);});

И он выведет это на консоль:

"a 1"
"a 2"
"a 3"
"b 5"

Предупреждение: см. комментарии ниже. Похоже, это было кратко названо sortByAll в версии 3, но теперь оно вернется к sortBy.

Ответ 2

Почему бы вам не использовать чистый javascript?

var foo = [
  {a: 'a', b: 2},
  {a: 'a', b: 1},
  {a: 'b', b: 5},
  {a: 'a', b: 3},
];
foo.sort (function (a,b) {
    return 2 * (a.a > b.a ? 1 : a.a < b.a ? -1 : 0) + 1 * (a.b > b.b ? 1 : a.b < b.b ? -1 : 0)
})

 /*
[
  {a: 'a', b: 1},
  {a: 'a', b: 2},
  {a: 'a', b: 3},
  {a: 'b', b: 5},
]
*/

Обновление: Heres более общий подход

function fieldSort (arr, fields) {
    return arr.slice().sort ( function (a,b) {
         return fields.reduce ( function (c,d,e,f) {
             var _a = a[d]||0,_b = b[d]||0
             return c + (f.length - e) * (_a>_b?1:_a<_b?-1:0)
        },0)
    })
} 
fieldSort (foo,["a","b"])

Обновление 2:

Если вы хотите поддерживать цепочку, вы можете добавить этот метод к прототипу loadash

_.prototype["fieldSort"] = (function (_) {
    function wrap (val,chain) {
        this.__wrapped__ = val;
        this.__chain__ = !!chain;
    }
    wrap.prototype = _.prototype
    function fieldSort(fields) {
        return this.slice().sort(function (a, b) {
            return fields.reduce(function (c, d, e, f) {
                var _a = a[d] || 0,
                    _b = b[d] || 0
                return c + (f.length - e) * (_a > _b ? 1 : _a < _b ? -1 : 0)
            },0)
        })
    }
    return function () {
         return new wrap (fieldSort.apply (this.__wrapped__,arguments),!!this.__chain__);
    };
})(_)
_(foo).fieldSort (["a","b"]);

Heres a Fiddle

Изменить примечания:
Спасибо @AndreasKöberle за рассказ о необязательном параметре reduce