Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/419.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript中数组的三向比较函数_Javascript_Arrays_Three Way Merge - Fatal编程技术网

Javascript中数组的三向比较函数

Javascript中数组的三向比较函数,javascript,arrays,three-way-merge,Javascript,Arrays,Three Way Merge,还有其他问题。我想知道的是编写/使用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 ] ] 是否有更像一

还有其他问题。我想知道的是编写/使用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 ] ]
是否有更像一行程序的东西,或者每当我想这样做时,我必须定义自己的函数


支持旧浏览器不是一项要求。使用jQuery或下划线之类的库是可以的


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

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

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

function compareArrays(lhs, rhs) {
    return combineNum(rhs) - combineNum(lhs);
}

可能不是最短的线路,但我能合理到达的最少线路是:

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 
<代码>功能对比显示(左、右、右){ 一些(函数(v,i){返回(r=vrhs[i]?1:0)}); 返回r; } [['a'、'b'、'c']、['a'、'c'、'd']、['a'、'b'、'd'].排序(比较数组)//a、b、c、a、b、d、a、c、d
但是compare函数需要知道它得到了什么,这样它就不会将数字作为字符串或字符串作为数字进行排序(等等…)。

我会选择一个通用的comparison maker函数,以功能化的方式使用它:

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); });
是否有更像一行程序的东西,或者每当我想这样做时,我必须定义自己的函数


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

您当前的解决方案不是“一行程序”吗?您可以使用and和条件运算符将排序函数缩减为几乎一行,但这只会将一个位置的代码量减少几个字符,而不会使其更快或更可靠。它不会比
comparararray()
函数小很多。“使用jQuery或下划线之类的库也可以。”-那么,把你的函数变成一个库。这就是你的一行程序。顺便说一句,你的函数对不同长度的数组不起作用。这还假设数组中的值总是数字,这对我来说并不总是如此。@JohnZwinck-是的,它确实假设是这样。你所有的例子都是数字的,所以我认为这就是你试图解决的问题。哦,那是我缩短它的机会。那么,你在这里的真正目标是什么?您有一个代码的工作示例。在您的项目中只需要有一个副本,然后您就可以引用它了。你为什么要把一行或两行删掉呢?这似乎是不需要牵扯这么一个琐碎的函数就可以实现的。我想我已经习惯了比较数组等更内置的语言……但即使如此,jQuery或下划线也应该能够做到这一点,而不必如此繁琐。而且,即使是我的工作函数也不是最优的:如果lhs.length与rhs.length非常不同,这会浪费时间……我可以添加更多的代码来解决这个问题,但如果有一个现有的函数可以做到这一点,这基本上是浪费时间。这也是假设它们是单个数字(或至少是相等的数量),而不是任何数字。@Bergi-是的,如果希望允许更大的数字,则可以根据需要分散权重因子。我只是想在这里提供另一个概念性的想法,不需要做太多的逐单元比较。谢谢——
some()
的使用很有趣,并且符合我对问题的概念表述。现在,如果有一个标准的“三方比较”函数与after在
sort()
中应用到string中的函数的语义相匹配……进一步考虑,我意识到我真正想要的
some()
更像返回回调生成的第一个truthy值,如果找不到,则返回指定的默认值。“我在下划线和Lo-dash中查找类似的内容,结果空手而归。此函数不适用于不同长度的数组。你认为你能很容易地适应它吗?@JohnZwinck这不是我的答案吗?返回第一个truthy结果,如果未找到,则默认为0。@Bergi yes,提供了有关如何处理这些结果的规则,例如,在rhs测试或类似测试中包含一个
i,如果返回false,则返回一个值。
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 
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)