如何在JavaScript中合并排序数组

如何在JavaScript中合并排序数组,javascript,Javascript,我有三个排序数组,如下所示 [{name:"a"}, {name:"b"}, {name:"m"}, {name:"x"}] [{name:"a"}, {name:"e"}, {name:"i"}, {name:"o"}] [{name:"g"}, {name:"h"}, {name:"m"}, {name:"n"}] 这些数组根据数组中每个对象的名称属性进行排序。下面是我从Java转换来合并两个排序数组的方法 function mergeSorted(a, b) { var answer

我有三个排序数组,如下所示

[{name:"a"}, {name:"b"}, {name:"m"}, {name:"x"}]
[{name:"a"}, {name:"e"}, {name:"i"}, {name:"o"}]
[{name:"g"}, {name:"h"}, {name:"m"}, {name:"n"}]
这些数组根据数组中每个对象的名称属性进行排序。下面是我从Java转换来合并两个排序数组的方法

function mergeSorted(a, b) {
  var answer = new Array(a.length + b.length), i = 0, j = 0, k = 0;
  while (i < a.length && j < b.length) {
    if (a[i].name < b[j].name) {
        answer[k] = a[i];
        i++;
    }else {
        answer[k] = b[j];
        j++;
    }
    k++;
  }
  while (i < a.length) {
    answer[k] = a[i];
    i++;
    k++;
  }
  while (j < b.length) {
    answer[k] = b[j];
    j++;
    k++;
  }
  return answer;
}
函数合并排序(a,b){
var-answer=新数组(a.length+b.length),i=0,j=0,k=0;
而(i

这是使用两个数组的工作小提琴。对于n个数组,实现相同效果的最佳方法是什么?我目前的想法是,一个接一个地将它与以前合并的数组合并,直到最后一项,就像n+=I一样。这是最好的方法吗

编辑以反映
异常
的原始解决方案,通过像
mergeSorted(mergeSorted(a,b),c)那样调用它进行扩展
比我这里的解决方案快


Javascript的内置排序速度[不够]快,以至于您可以将所有数组连接在一起,然后一次性对整个内容进行排序。Javascript不适合重新实现应该在较低级别完成的事情

var a1 = [{name:"a"}, {name:"b"}, {name:"m"}, {name:"x"}]
var a2 = [{name:"a"}, {name:"e"}, {name:"i"}, {name:"o"}]
var a3 = [{name:"g"}, {name:"h"}, {name:"m"}, {name:"n"}]

a1.concat(a2,a3).sort(function(a,b){return (a.name>b.name)-(a.name<b.name)})
// [{name:"a"}, {name:"a"}, {name:"b"}, {name:"e"}, {name:"h"}, {name:"i"}, {name:"g"}, {name:"m"}, {name:"m"}, {name:"n"}, {name:"o"}, {name:"x"}]
var a1=[{name:“a”},{name:“b”},{name:“m”},{name:“x”}]
var a2=[{name:“a”},{name:“e”},{name:“i”},{name:“o”}]
var a3=[{name:“g”},{name:“h”},{name:“m”},{name:“n”}]
a1.concat(a2,a3).sort(函数(a,b){return(a.name>b.name)-(a.name更新:
考虑到当前年份的情况,现在应该是:

const mergeAll = (...arrays) => arrays.reduce(mergeSorted);
原件: 如果您感觉功能正常,这是一个使用reduce的完美场所

var mergeAll = function(){
    return Array.prototype.slice.call(arguments).reduce(mergeSorted);
};
例如:

var a = [{name:"a"}, {name:"b"}, {name:"m"}, {name:"x"}];
var b = [{name:"a"}, {name:"e"}, {name:"i"}, {name:"o"}];
var c = [{name:"g"}, {name:"h"}, {name:"m"}, {name:"n"}];

console.log(mergeAll(a,b,c).map(function(x){return x.name;}));

jsfiddle:

本机实现并不总是最快的(正如您可能已经注意到的)而且,从历史上看,由于广泛的错误检查,性能一直比较缓慢。也就是说,由于与硬件或专门为优化某些任务而构建的例程进行了更强大的集成,未来可能会有性能增强。如果您编写自己的代码,您的应用程序将无法利用这些boo一旦它们被实施,性能就会下降。这取决于你决定优势在哪里,风险在哪里

无论如何,我已经为您的优化代码编写了一个更漂亮的版本:

function mergeSorted(a,b){
    var alen = a.length
      , blen = b.length
      , i, j, k = j = i = 0
      , answer = new Array(alen + blen)
    ;//var

    while(i < alen && j < blen)
                    answer[k++] = a[i].name < b[j].name ? a[i++] : b[j++];
    while(i < alen) answer[k++] = a[i++];
    while(j < blen) answer[k++] = b[j++];

    return answer;
}
函数合并排序(a,b){
var alen=a.length
,blen=b.长度
,i,j,k=j=i=0
,answer=新阵列(alen+blen)
;//var
而(i
更快,只需一次合并,更具灵活性(keepDuplicates,自定义比较器):


注意:如果您有大量数组,则在
insertNextIndex()
中使用a而不是线性搜索,或者使用for
next
我认为最标准、最容易理解的代码,可能会使您受益

function mergeArray(arr1, arr2) {
 var new_array = [];
 var i = 0,
     j = 0,
     index = 0;

 while (new_array.length != (arr1.length + arr2.length) - 1) {
     if (arr1[i] < arr2[j]) {
         new_array.push(arr1[i]);
         i++;
     } else {
         new_array.push(arr2[j]);
         j++;
     }
 }
 return new_array;
}

您是否正在尝试做一些比合并数组并重新调用更快的事情?@jfriend00 Server将以单独排序的数组向我发送数据,我认为如果我能够实现合并,速度会更快。这些数组有多大?@JoeFrambach 10K个项目,每个对象中有5-6个属性您的代码在这个基准测试中战胜了mine:所有语言的高级实现很少能打败内部的低级实现,这通常不是真的吗?通常是的。我同意。这很酷。打败这种语言很有趣。不过,你的阅读效果要好得多。我想知道是连接速度慢,还是排序速度慢。这甚至不是问题的解决方案,beca使用它完全无法利用输入的预排序特性。非常好的
mergeAll
函数!我喜欢它!这是一个可怕的解决方案。您正在进行n次合并。这将比从n个源进行单个合并的性能差得多。我不明白为什么这会是公认的答案。这是一个错误,因为
j
may超出了
arr2
的界限。未能通过testcase
mergeArray([2,3],[1])
,返回
[1,未定义]
mergeSortedArrays(arrays, true, function(a, b) {
    return a.name < b.name ? -1 : 1;
});
function mergeArray(arr1, arr2) {
 var new_array = [];
 var i = 0,
     j = 0,
     index = 0;

 while (new_array.length != (arr1.length + arr2.length) - 1) {
     if (arr1[i] < arr2[j]) {
         new_array.push(arr1[i]);
         i++;
     } else {
         new_array.push(arr2[j]);
         j++;
     }
 }
 return new_array;
}
var merged_array = mergeArray([1,6,9,95], [2,7,10,11,14,18]);