如何使用lodash / underscore按多个嵌套字段排序?

时间:2014-06-08 22:27:22

标签: javascript underscore.js lodash

我想做这样的事情:

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

data = _.sortBy(data, ["sortData.a", "sortData.b"]);

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

并输出此信息:

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

不幸的是,这不起作用,数组仍以其原始形式排序。 This would work if the fields weren't nested inside the sortData.如何使用lodash / underscore按多个嵌套字段对对象数组进行排序?

我已将此转换为lodash功能请求:https://github.com/lodash/lodash/issues/581

7 个答案:

答案 0 :(得分:36)

更新:请参阅下面的评论,在大多数情况下,这不是一个好的解决方案。


有人回答in the issue I created。这是他的答案,内联:

_.sortBy(data, function(item) {
   return [item.sortData.a, item.sortData.b];
});

我没有意识到你被允许从该函数返回一个数组。文档没有提到这一点。

答案 1 :(得分:19)

如果您需要指定排序方向,可以将_.orderBy Lodash 4.x 中的函数数组语法一起使用:

_.orderBy(data, [
  function (item) { return item.sortData.a; },
  function (item) { return item.sortData.b; }
], ["asc", "desc"]);

这将首先按属性a升序排序,对于属性a具有相同值的对象,将按属性b降序排序。

ab属性具有不同类型时,它会按预期工作。

以下是使用此语法的jsbin example

答案 2 :(得分:17)

lodash版本3中有_.sortByAll方法:

https://github.com/lodash/lodash/blob/3.10.1/doc/README.md#_sortbyallcollection-iteratees

Lodash第4版,已统一:

https://lodash.com/docs#sortBy

其他选择是自己对值进行排序:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

function compareValues(v1, v2) {
    return (v1 > v2) 
        ? 1 
        : (v1 < v2 ? -1 : 0);
};


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

data.sort(function (x, y) {
    var result = compareValues(x.a, y.a);

    return result === 0 
        ? compareValues(x.b, y.b) 
        : result;
});

// data after sort:
// [
//     { a: 1, b: 3 },
//     { a: 2, b: 1 },
//     { a: 2, b: 2 }
// ];

答案 3 :(得分:10)

真棒,简单的方法是:

_.sortBy(data, [function(item) {
    return item.sortData.a;
}, function(item) {
    return item.sortData.b;
}]);

我从检查lodash的源代码中找到它,它总是逐个检查函数。

希望有所帮助。

答案 4 :(得分:6)

使用ES6 easy语法和lodash

sortBy(item.sortData, (item) => (-item.a), (item) => (-item.b))

答案 5 :(得分:0)

我认为这在大多数情况下可以使用下划线:

var properties = ["sortData.a", "sortData.b"];
data = _.sortBy(data, function (d) {
    var predicate = '';
    for (var i = 0; i < properties.length; i++)
    {
        predicate += (i == properties.length - 1 
                           ? 'd.' + properties[i]
                           : 'd.' + properties[i] + ' + ')
    }
    return eval(predicate)
});

It works and you can see it in Plunker

答案 6 :(得分:0)

如果问题是整数转换为字符串,则在整数之前添加零,使其长度与集合中最长的相同:

var maxLength = _.reduce(data, function(result, item) {
    var bString = _.toString(item.sortData.b);
    return result > bString.length ? result : bString.length;            
}, 0);

_.sortBy(data, function(item) {
    var bString = _.toString(item.sortData.b);
    if(maxLength > bString.length) {
        bString = [new Array(maxLength - bString.length + 1).join('0'), bString].join('');
    }

    return [item.sortData.a, bString];
});