在Javascript中订购列表

时间:2016-02-16 19:29:44

标签: javascript sorting lodash

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

[ [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这样的公共库)中获取适当的嵌套列表?

5 个答案:

答案 0 :(得分:2)

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

&#13;
&#13;
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))
&#13;
&#13;
&#13;

答案 1 :(得分:1)

编辑:好的,受到@ Damien的回答的启发,这很脏但会完美运作。希望我能管理更清洁的东西。

您可以使用lodash's differenceWith来压缩&#39;每个值的数组等于。但是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
});

Fiddle

答案 2 :(得分:1)

您可以使用_.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)

答案 3 :(得分:0)

您可以使用自定义排序功能,请参阅此doc

示例:

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

你可能需要处理更多边缘情况,但你有这个想法。

答案 4 :(得分: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 ] ] ]