Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quickest way to sort a JS array based on another array's values?

There's some similar posts knocking about but I cant find anything that quite addresses this particular issue... I have two arrays of paired values:

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

What's the most processor friendly way to sort the arrays so that array A is in numerical ascending order and the data structure is maintained? I guess built in array.sort(function) would be quickest but I'm not confident of the syntax.

like image 696
cronoklee Avatar asked Mar 25 '11 00:03

cronoklee


2 Answers

Kind of hacky, but it works.

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.

Output

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

Basically, we are making objects with a clear tie between A and B within a new array, and then sort()ing that.

Then I go back and rebuild the original the two arrays.

Update

Már Örlygsson makes a good point in the comments. Instead of producing an object like {A: 0.5, B: 'a'}, he suggests placing the A an B values in arrays like [0.5, 'a'].

This should be faster, though it will be slightly less readable if needing to debug the all array. I'll leave this up to you, if you are experiencing performance issues, profile both these methods and choose the fastest.

like image 20
alex Avatar answered Sep 28 '22 03:09

alex


I noticed all the above solutions used a map. Another method that saves a bit of memory is to create an array of indices, sort the indices based on A, and then reconstruct A and B based on the indices.

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>';

here's the jsfiddle

EDIT: semi-one-liner inspired by 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];});
like image 166
woojoo666 Avatar answered Sep 28 '22 05:09

woojoo666