1

还有其他关于如何在 JavaScript 中比较数组的问题?. 我想知道的是编写/使用像 Array.sort() 所需的三路比较函数的最直接方法。这是一个使用默认设置的示例,但效果不佳:

> [ [4,5,10], [4,5,6], [4,1,2] ].sort() // no compare function, uses the default one
[ [ 4, 1, 2 ],
  [ 4, 5, 10 ], // oops, string sorting makes 10 < 6
  [ 4, 5, 6 ] ]

这就是我想出的:

// return -1 if lhs is "less" than rhs, +1 if "greater", and 0 if equal
// if lhs and rhs have different lengths, only the shorter part will be considered
function compareArrays(lhs, rhs) {
  for (var ii = 0; ii < lhs.length; ii++) {
    if (lhs[ii] < rhs[ii]) {
      return -1;
    } else if (lhs[ii] > rhs[ii]) {
      return 1;
    }
  }
  return 0;
}

这给了我们想要的东西:

> [ [4,5,10], [4,5,6], [4,1,2] ].sort(compareArrays)
[ [ 4, 1, 2 ],
  [ 4, 5, 6 ],
  [ 4, 5, 10 ] ]

是否有更像单线的东西,或者我必须在任何时候定义自己的函数?

支持旧浏览器不是必需的。使用 jQuery 或 Underscore 之类的库是可以的。

看待这一点的一种方法是“应用于每对元素的标准三向比较中的第一个非零值”。但即便如此,我也没有在现有的库中找到合适的选择。

4

3 回答 3

1

可能不是最短的,但我能理解的最少的行是:

function compareArrays(lhs, rhs) {
  var result;
  lhs.some(function(v, i) {
    return (result = v - rhs[i]);
  });
  return result;
}

或更不明智:

function compareArrays(lhs, rhs, r) {
  lhs.some(function(v, i) {return (r = v - rhs[i])});
  return r;
}

编辑

似乎你不想要数字。比较部分可以是您想要的任何关系,例如字符串:

function compareArrays(lhs, rhs, r) {
  lhs.some(function(v, i) {return (r = v < rhs[i]? -1 : v > rhs[i]? 1 : 0)});
  return r;
}

[['a','b','c'],['a','c','d'],['a','b','d']].sort(compareArrays) // a,b,c,a,b,d,a,c,d 

但是比较函数需要知道它得到了什么,因此它不会将数字排序为字符串或将字符串排序为数字(等等......)。

于 2014-05-27T06:29:00.510 回答
1

我会选择一个通用的比较器函数,以一种功能性的方式使用:

function compareArrays(compareItems) {
    return function(a, b) {
        for (var r, i=0, l=Math.min(a.length, b.length); i<l; i++)
            if (0 != (r = compareItems(a[i], b[i])))
                return r;
        return a.length - b.length;
     };
}
// Examples:
var compareNumberArrays = compareArray(function(a,b){ return a-b; }),
    compareGenericArrays = compareArray(function(a,b){ return +(a>b)||-(b>a); });

现在你可以使用

[ [4,5,10], [4,5,6], [4,1,2], [4,5] ].sort(compareNumberArrays)

是否有更像单线的东西,或者我必须在任何时候定义自己的函数?

比较数组对于单行来说太复杂了,您应该使用辅助函数。没有可以在任何地方使用的内置软件。

于 2014-05-27T07:03:47.943 回答
0

如果你知道它们总是三元组数字(长度为 3 的数组),你可以这样做:

function combineNum(array) {
    return (array[0] * 100) + (array[1] * 10) + array[2];
}

function compareArrays(lhs, rhs) {
    return combineNum(rhs) - combineNum(lhs);
}
于 2014-05-27T06:04:48.870 回答