Sorting an array according to another sorted array index
I have two arrays. I have to do a normal sort on one (descending or ascending) and sort the other according to how the first array is sorted. This is because every element in the first array is related to the same index element in the second array, and I have to keep this relationship true. For example:
sortThis=[3,1,2];
sortAccording=["With 3","With 1","With 2];
I could not find a way to change the index using a JavaScript function sort
.
source to share
Solution: To achieve this, you must anchor both arrays with just one. This means that you have these two arrays:
sortThis=[3,1,2];
sortAccording=["With 3","With 1","With 2];
After zip, they will have the following array:
zipped = [{a: 3, b: "With 3"}, {a: 1, b: "With 1"}, {a: 2, b: "With 2"}];
Then you sort it by a to have:
zippedAndSorted = [{a: 1, b: "With 1"}, {a: 2, b: "With 2"}, {a: 3, b: "With 3"}];
What's next?
Well, if you have this array sorted by what you want, you have to extract their values ββusing the map function , and finally you will have your two arrays sorted by the same criteria:
Code:
// your arrays
sortThis=[3,1,2];
sortAccording=["With 3","With 1","With 2"];
// the zip function
function zip(a,b) {
return a.map(function(aa, i){ return { i: aa, j: b[i]};} )
};
// ziping and sorting the arrays
var zipped = zip(sortThis, sortAccording);
zippedAndSorted = zipped.sort(function(a,b){ return a.i - b.i; });
// your two sorted arrays
sortedThis = zippedAndSorted.map(function(a){ return a.i;});
sortedAccording = zippedAndSorted.map(function(a){ return a.j;});
You can also see how it works here: http://jsfiddle.net/lontivero/cfpcJ/
Good luck!
source to share
For example:
function zip(a, b) {
var i = 0, j = 0, r = [];
while(i < a.length && j < b.length)
r.push([a[i++], b[j++]]);
return r;
}
function unzip(r) {
var a = [], b = [];
for(var i = 0; i < r.length; i++) {
a.push(r[i][0]);
b.push(r[i][1]);
}
return [a, b];
}
r = zip(sortAccording, sortThis);
r.sort();
r = unzip(r);
sortAccording = r[0]
sortThis = r[1]
Another way:
result = sortAccording.
map(function(elem, pos) { return [elem, pos]}).
sort().
map(function(elem) { return sortThis[elem[1]]})
More efficient implementations of zip and unzip (both operate on a variable number of arguments):
zip = function() {
var args = [].slice.call(arguments, 0);
return args[0].map(function(_, i) {
return args.map(function(a) {
return a[i]
})
})
}
unzip = function(a) {
return a[0].map(function(_, i) {
return a.reduce(function(y, e) {
return y.concat(e[i])
}, [])
})
}
source to share
I have a simple solution. Create a third array of indices. Just sort this indexed array based on the first array.
var indexArray = [];
for (var i=0; i < sortThis.length; i++) {
indexArray[i] = i;
}
indexArray.sort(function(a, b) {
return (sortThis[a] > sortThis[b]) ? 1 : (sortThis[a] === sortThis[b]) ? 0 : -1;
});
// Now you have the sorted index ready
console.log("The first elements in the arrays are: " + sortThis(indexArray[0]) + " and " + sortAccording(indexArray[0]));
source to share