How can I use lodash/underscore to sort by multiple nested fields?

前端 未结 7 1169
情话喂你
情话喂你 2021-02-03 21:51

I want to do something like this:

var data = [
    {
        sortData: {a: \'a\', b: 2}
    },
    {
        sortData: {a: \'a\', b: 1}
    },
    {
        sort         


        
相关标签:
7条回答
  • 2021-02-03 22:28

    If you need to specify the sort direction, you can use _.orderBy with the array of functions syntax from Lodash 4.x:

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

    This will sort first ascending by property a, and for objects that have the same value for property a, will sort them descending by property b.

    It works as expected when the a and b properties have different types.

    Here is a jsbin example using this syntax.

    0 讨论(0)
  • 2021-02-03 22:29

    With ES6 easy syntax and lodash

    sortBy(item.sortData, (item) => (-item.a), (item) => (-item.b))
    
    0 讨论(0)
  • 2021-02-03 22:32

    There is a _.sortByAll method in lodash version 3:

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

    Lodash version 4, it has been unified:

    https://lodash.com/docs#sortBy

    Other option would be to sort values yourself:

    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 }
    // ];
    
    0 讨论(0)
  • 2021-02-03 22:37

    I think this could work in most cases with underscore:

    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

    0 讨论(0)
  • 2021-02-03 22:38

    The awesome, simple way is:

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

    I found it from check the source code of lodash, it always check the function one by one.

    Hope that help.

    0 讨论(0)
  • 2021-02-03 22:40

    If the problem is an integer is converted to a string, add zeroes before the integer to make it have the same length as the longest in the collection:

    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];
    });
    
    0 讨论(0)
提交回复
热议问题