基于另一个数组的值对JS数组进行排序的最快方法?

时间:2011-03-25 00:10:07

标签: javascript arrays

有一些类似的帖子敲响了但是我找不到任何可以解决这个特定问题的事情...... 我有两个配对值数组:

var A=[0.5, 0.6, 0.5, 0.7, 0.8, 0.1]
var B=['a','b','c','d','e','f']
//note: a=0.5, b=0.6, c=0.5, d=0.7, etc

对数组进行排序的处理器最友好的方法是什么,以便数组A按数字升序排列并保持数据结构?我想内置的array.sort(函数)会最快,但我对语法没有信心。

7 个答案:

答案 0 :(得分:12)

有点hacky,但它确实有效。

var A = [0.5, 0.6, 0.5, 0.7, 0.8, 0.1];
var B = ['a', 'b', 'c', 'd', 'e', 'f'];

var all = [];

for (var i = 0; i < B.length; i++) {
    all.push({ 'A': A[i], 'B': B[i] });
}

all.sort(function(a, b) {
  return a.A - b.A;
});

A = [];
B = [];

for (var i = 0; i < all.length; i++) {
   A.push(all[i].A);
   B.push(all[i].B);
}    

console.log(A, B);

jsFiddle

输出

0.1, 0.5, 0.5, 0.6, 0.7, 0.8
["f", "a", "c", "b", "d", "e"]

基本上,我们在新数组中制作AB之间明确关系的对象,然后sort()

然后我回去重建原来的两个阵列。

更新

Már Örlygsson在评论中提出了一个很好的观点。他建议不要生成像{A: 0.5, B: 'a'}这样的对象,而是将AB值放在[0.5, 'a']等数组中。

这个应该更快,但如果需要调试all数组,它的可读性会稍差。如果您遇到性能问题,请将这些方法分析出来,并选择最快的方法。

答案 1 :(得分:9)

我注意到以上所有解决方案都使用了地图。另一种节省内存的方法是创建一个索引数组,根据A对索引进行排序,然后根据索引重建A和B.

var A=[0.5, 0.6, 0.5, 0.7, 0.8, 0.1];
var B=['a','b','c','d','e','f'];
var indices = A.map(function(elem, index){return index;}); //an array of indices
indices.sort(function (a,b) {return A[a] - A[b];});

//print out the results
for (var i = 0; i < A.length; i++)
    document.body.innerHTML += 'A: ' + A[indices[i]] + ', B: ' + B[indices[i]] + '<br>';

这是jsfiddle

编辑:受chowey's comment启发的半单线:

var BSorted = A.map(function(e,i){return i;})
               .sort(function(a,b){return A[a] - A[b];})
               .map(function(e){return B[e];});

答案 2 :(得分:4)

如果你有一个带有元组的数组而不是两个数组会更简单。因为那样你就可以使用内置Array.sort()

var arr = [{a: 0.5, b: 'a'}, {a: 0.6, b: 'b'}, {a: 0.5, b: 'c'}, ... ];

在此之后你可以写:

arr.sort(function(x,y) { return x.a - y.a });

答案 3 :(得分:1)

Array.prototype.swap=function(a, b)
{
    var tmp=this[a];
    this[a]=this[b];
    this[b]=tmp;
}

function partition(array, array2, begin, end, pivot)
{
    var piv=array[pivot];
    array.swap(pivot, end-1);
    array2.swap(pivot, end-1);
    var store=begin;
    var ix;
    for(ix=begin; ix<end-1; ++ix) {
        if(array[ix]<=piv) {
            array.swap(store, ix);
            array2.swap(store, ix);
            ++store;
        }
    }
    array.swap(end-1, store);
    array2.swap(end-1, store);

    return store;
}

function qsort(array, array2, begin, end)
{
    if(end-1>begin) {
        var pivot=begin+Math.floor(Math.random()*(end-begin));

        pivot=partition(array, array2, begin, end, pivot);

        qsort(array, array2, begin, pivot);
        qsort(array, array2, pivot+1, end);
    }
}

数组用于数字, array2用于字符串, 它们的长度必须相同。

这是快速排序所以时间是O(N LogN)

source是literateprograms.org,许可证是麻省理工学院,修改以管理我制作的第二个阵列

答案 4 :(得分:0)

使用任何排序算法,在算法时间和其他约束(通常是内存)之间存在权衡。您可能需要查看QuicksortBubble Sort两种常见且非常快速的排序算法。您需要进行微小的修改,因为您实际上正在排序两个数组,第一个是要排序的数据源 - 但这种变化很简单。

编辑:注意,array.sort()不适合你,因为你希望arr1中的更改​​反映在arr2中。你必须编写自己的排序功能

答案 5 :(得分:0)

之前将两个阵列放在一起 排序是最简单的方法。

var a1, b1, A= [0.5, 0.6, 0.5, 0.7, 0.8, 0.1],
B= ['a', 'b', 'c', 'd', 'e', 'f'],    
ab= A.map(function(itm, i){ return [itm, i]; });

ab.sort(function(a, b){ return a[0]-b[0]; });

B= ab.map(function(itm){
    A.push(itm[0]);
    return B[itm[1]];
});
A= A.splice(B.length);

alert(A+'\n'+B)

/*  returned value: (String)
0.1, 0.5, 0.5, 0.6, 0.7, 0.8
f, a, c, b, d, e
*/

答案 6 :(得分:-1)

如果可能的话,你可能会更好,实际上是建立一个数据结构。这样,您可以在保持结构的同时基于一个属性对$A[]进行排序。我没有做任何速度测试或任何事情,但也许像... ...

A[0]['label']='a';
A[0]['value']=0.5;

A[1]['label']='b';
A[1]['value']=0.6;

A[2]['label']='c';
A[2]['value']=0.5;

A[3]['label']='d';
A[3]['value']=0.7;

A[4]['label']='e';
A[4]['value']=0.8;

A[5]['label']='f';
A[5]['value']=0.1;