【问题标题】:How can I use lodash/underscore to sort by multiple nested fields?如何使用 lodash/underscore 按多个嵌套字段排序?
【发布时间】:2014-07-29 11:27:16
【问题描述】:

我想做这样的事情:

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

【问题讨论】:

    标签: javascript underscore.js lodash


    【解决方案1】:

    如果您需要指定排序方向,您可以使用_.orderByLodash 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】:

    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】:

      使用 ES6 简单的语法和 lodash

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

      【讨论】:

      • 这只是一种消极的排序方式,当你这样做时,你不需要反转数组。
      • 漂亮,我喜欢 ES6 的简单性!
      【解决方案4】:

      真棒,简单的方法是:

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

      查lodash的源码发现的,总是一一检查函数。

      希望有所帮助。

      【讨论】:

      • 另外,如果您想对这些排序函数中的任何一个进行“反向”排序,只需在返回的值中添加一个“-”即可。以return -item.sortData.a; 为例。
      【解决方案5】:

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

      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];
      });
      

      【讨论】:

        【解决方案6】:

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

        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

        【讨论】:

          【解决方案7】:

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


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

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

          我没有意识到您可以从该函数中返回一个数组。文档没有提到这一点。

          【讨论】:

          • 这是因为当您返回一个数组时,它会转换为字符串然后进行比较,但是如果您的第二个项目是数字并且您想按第二个值作为数字进行排序,它将不起作用。
          猜你喜欢
          • 1970-01-01
          • 2013-05-03
          • 1970-01-01
          • 2015-11-22
          • 2015-10-24
          • 2018-09-13
          • 2021-09-24
          • 2022-11-29
          • 1970-01-01
          相关资源
          最近更新 更多