在 Javascript 中对列表进行排序

Ordering lists in Javascript

本文关键字:排序 列表 Javascript      更新时间:2023-09-26

我有一个列表,其成员是整数的嵌套列表,例如:

[ [1,2], [], [1,2,3], [ [1,2],3], [1,2,4], [ [], [1,2] ], [34,5,6], [-1,66] ]

我想对这个列表进行排序,使用(世界上所有其他语言(会考虑嵌套列表的标准排序。例如:

[] < [ [1] ] < [ [1,2] ] < [ [2] ] < [ [11] ]

l.sort()搞砸了,因为它将列表变成了字符串

有没有一种简单的方法,无论是在javascript(还是像lodash这样的公共库(中,都可以获得适当的嵌套列表?

这是一个由两个相互递归函数组成的系统,第一个将数组与非数组进行比较,将数字与数字进行比较,第二个将数组与元素进行比较。

function cmp(x, y) {
    let ax = Array.isArray(x),
        ay = Array.isArray(y);
    return ax - ay || (ax ? cmpArr(x, y) : x - y);
}
function cmpArr(x, y) {
    let xlen = x.length,
        ylen = y.length,
        min = xlen < ylen ? xlen : ylen,
        c;
    for (let i = 0; i < min; i++) {
        if (c = cmp(x[i], y[i]))
            return c;
    }
    return xlen - ylen;
}
//
a = [[1, 2], [], [1, 2, 3], [[1, 2], 3], [1, 2, 4], [[], [1, 2]], [34, 5, 6], [-1, 66]];
a.sort(cmp);
console.log(JSON.stringify(a))

您可以使用 _.sortBy 作为快捷方式。

_.sortBy(arr, function (o) { return o[0] || Infinity } )

或者,如果内部数组尚未排序:

_.sortBy(arr, function (o) { return someMutatedArr[0] || Infinity } )

编辑:

我找到了一种更好的方法,可以在列表中第一项之外进行排序,但空数组仍在末尾。你可以单独处理这个边缘情况,我知道这很烦人。

var arr = [ [11], [1,3], [2], [], [1], [1,2]]
var count = []
// Get an array that is as long as the longest array with [0, 1, 2, etc]
arr.forEach(function (e, i) { 
  if (e.length > (count.length) ) 
    count.push(count.length -1) 
})
_.sortBy(arr, count)

编辑 : 好的,受到@Damien回答的启发,这很脏,但可以完美地工作。希望我能管理一些更干净的东西。

您可以使用 lodash 的 differenceWith 来"压缩"每个值的数组,这些值是相等的。但是jsfiddle没有最新版本的lodash,所以我无法测试它。

var l = [[1,2],[],[1,3],[34, 5, 6],[-1, 66]];
l = l.sort(function(a, b) {
  var minLength = Math.min(a.length, b.length);
  for (var i = 0; i < minLength; i++) { // Compare the "matching pairs"
    if (a[i] < b[i]) {
      return -1;
    } else if(a[i] > b[i]){
        return 1;
    }
  }
  return a.length - b.length; // If all pairs were equals, use list length
});

小提琴

您可以使用自定义排序函数,请参阅此文档。

例:

var l = [[1,2], [], [34,5,6], [-1,66]];
l = l.sort(function (a, b) {
  if(!a.length) {
      return -1; 
  }
  if(!b.length) {
      return 1; 
  }
  return a[0] - b[0];
});

您可能需要处理更多的边缘情况,但您在这里有想法。

var res = _.chain(items)
    .groupBy(function (item) {
        return _.chain(item).flattenDeep().max().value() || -1;
    })
    .map(function(val, key){
        return {
            key: parseFloat(key),
            val: val
        };
    })
    .orderBy('key')
    .map(function(item){
        return _.sortBy(item.val, 'length');
    })
    .flatten()
    .value();

[[], [ [1] ], [ [1,2] ], [ [2] ], [ [11] ]]

结果是

[ [], [ [ 1 ] ], [ [ 1, 2 ] ], [ [ 2 ] ], [ [ 11 ] ] ]