Sort an array of objects by dynamically provided list of object properties in a order by then by style

后端 未结 5 1467
渐次进展
渐次进展 2021-01-19 23:42

How to write a generic sorting function in the style orderBy thenBy that sort an array by a list of properties provided as an array.

相关标签:
5条回答
  • 2021-01-20 00:03

    Thanks for all great answers. For information, I discovered that a recursive approach is also an alternative solution

    function sortByThenBy(items, keys) {
        return items.sort(function(it1, it2){return compare(it1, it2, keys);});
    }
    
    function compare(it1, it2, keys, index) {
        index = index || 0;
        var currentKey = keys[index];
        return it1[currentKey] < it2[currentKey] ? 1 : (it1[currentKey] > it2[currentKey] ? -1 : compare(it1, it2, keys, index + 1));
    } 

    0 讨论(0)
  • 2021-01-20 00:07

    I think you can do as follows;

    function sortBy(a,p){
      return a.sort(function(a,b){
                      var sp = p.find(k => a[k] - b[k]); // find the property to compare;
                      return a[sp] - b[sp];
                    });
    }
    
    var items = [{ name: "AA", prop1 : 12, prop2: 13, prop3: 5, prop4: 26 },
                 { name: "AA", prop1 : 12, prop2: 13, prop3: 6, prop4: 23 },
                 { name: "AA", prop1 : 12, prop2: 14, prop3: 5, prop4: 23 },
                 { name: "AA", prop1 : 11, prop2: 13, prop3: 5, prop4: 22 },
                 { name: "AA", prop1 : 10, prop2: 13, prop3: 9, prop4: 21 }
                ];
    console.log(sortBy(items,["prop1", "prop3", "prop4"]));
    console.log(sortBy(items,["prop1", "prop3"]));
    console.log(sortBy(items,["prop4", "prop3"]));

    0 讨论(0)
  • 2021-01-20 00:10

    try this solution.I'm creating sequence with data used in comparision like data1|0000NumberData2|data3. After that using native sort JS function to compare this sequence.

    To avoid string comparision problem with numbers - zero padding used 000000345

    So you can specify fields to use and fields sequence.

    var items = [{ name: "AA", prop1 : 12, prop2: 13, prop3: 5, prop4: 22 },
                 { name: "AA", prop1 : 2, prop2: 13, prop3: 6, prop4: 23 },
                 { name: "AB", prop1 : 12, prop2: 14, prop3: 5, prop4: 23 },
                 { name: "AA", prop1 : 11, prop2: 13, prop3: 5, prop4: 22 },
                 { name: "AA", prop1 : 10, prop2: 13, prop3: 9, prop4: 21 }];
    
    // sort by prop1 then by prop3 then by prop4:
    var sortedItems = sortByThenBy(items, ["prop1", "prop3", "prop4"]);
    console.log(sortedItems);
    
    // sort by prop1 then by prop3:
    var sortedItems = sortByThenBy(items, ["prop1", "prop3"]);
    console.log(sortedItems);
    
    function sortByThenBy(items, props) {
      return items.sort(function(a, b) {
        var a_path = $.map(props, function(item) {
          var ret = a[item];
          return isNumber(ret) ? pad(ret, 10) : ret;
        }).join('|');
        
        var b_path = $.map(props, function(item) {
          var ret = b[item];
          return isNumber(ret) ? pad(ret, 10) : ret;
        }).join('|');
        
        return a_path > b_path ? 1 : (a_path == b_path ? 0 : -1);
      });
    }
     
    function isNumber(n) {
       return !isNaN(parseFloat(n)) && isFinite(n);
    }
    
    function pad(n, width) {
      n = n + '';
      return n.length >= width ? n : new Array(width - n.length + 1).join('0') + n;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>

    0 讨论(0)
  • 2021-01-20 00:11

    Do it using Array#sort and Array#reduce methods.

    function sortByThenBy(arr, props) {
      // apply custom sort function on array
      return arr.sort(function(a, b) {
        // generate compare function return value by 
        // iterating over the properties array
        return props.reduce(function(bool, k) {
          // if previous compare result is `0` then compare
          // with the next property value and return result
          return bool || (a[k] - b[k]);
          // set initial value as 0
        }, 0);
      })
    }
    

    var items = [{
      name: "AA",
      prop1: 12,
      prop2: 13,
      prop3: 5,
      prop4: 22
    }, {
      name: "AA",
      prop1: 12,
      prop2: 13,
      prop3: 6,
      prop4: 23
    }, {
      name: "AA",
      prop1: 12,
      prop2: 14,
      prop3: 5,
      prop4: 23
    }, {
      name: "AA",
      prop1: 11,
      prop2: 13,
      prop3: 5,
      prop4: 22
    }, {
      name: "AA",
      prop1: 10,
      prop2: 13,
      prop3: 9,
      prop4: 21
    }];
    
    console.log(sortByThenBy(items, ["prop1", "prop3", "prop4"]));
    
    console.log(sortByThenBy(items, ["prop1", "prop3"]));
    
    console.log(sortByThenBy(items, ["prop2", "prop3"]));
    
    
    function sortByThenBy(arr, props) {
      return arr.sort(function(a, b) {
        return props.reduce(function(bool, k) {
          return bool || (a[k] - b[k]);
        }, 0);
      })
    }
    .as-console-wrapper {
      max-height: 100% !important;
      top: 0;
    }

    0 讨论(0)
  • 2021-01-20 00:13

    You could iterate the keys and use Array#some for getting the order value.

    This proposal works with a short circuit, if a delta is truthy (!== 0), then the iteration breaks and the delta is returned to the sort callback.

    function sortByThenBy(array, keys) {
        return array.sort(function (a, b) {
            var r = 0;
            keys.some(function (k) {
                return r = a[k] - b[k];
            });
            return r;
        });
    }
    
    var items = [{ name: "AA", prop1: 12, prop2: 13, prop3: 5, prop4: 22 }, { name: "AA", prop1: 12, prop2: 13, prop3: 6, prop4: 23 }, { name: "AA", prop1: 12, prop2: 14, prop3: 5, prop4: 23 }, { name: "AA", prop1: 11, prop2: 13, prop3: 5, prop4: 22 }, { name: "AA", prop1: 10, prop2: 13, prop3: 9, prop4: 21 }];
    
    console.log(sortByThenBy(items, ["prop1", "prop3", "prop4"]));
    console.log(sortByThenBy(items, ["prop1", "prop3"]));
    console.log(sortByThenBy(items, ["prop3", "prop1", "prop4"]));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    0 讨论(0)
提交回复
热议问题