I have a list of objects:
[ { id: 4, name:\'alex\' }, { id: 3, name:\'jess\' }, { id: 9, name:\'...\' }, { id: 1, name:\'abc\' } ]
I have a
I think the best way you'll find is to put all the elements of the first list into a hash using the id values as the property name; then build the second list by iterating over the list of ids, looking up each object in the hash, and appending it to the list.
DEMO
function sort(array, order) {
//create a new array for storage
var newArray = [];
//loop through order to find a matching id
for (var i = 0; i < order.length; i++) {
//label the inner loop so we can break to it when match found
dance:
for (var j = 0; j < array.length; j++) {
//if we find a match, add it to the storage
//remove the old item so we don't have to loop long nextime
//and break since we don't need to find anything after a match
if (array[j].id === order[i]) {
newArray.push(array[j]);
array.splice(j,1);
break dance;
}
}
}
return newArray;
}
var newOrder = sort(oldArray,[3, 1, 9, 4]);
console.log(newOrder);
I stepped in this problem and solved it with a simple .sort
Assuming that your list to be sorted is stored in the variable needSort
and the list with the order is in the variable order
and the both are in the same scope you can run a .sort
like this:
needSort.sort(function(a,b){
return order.indexOf(a.id) - order.indexOf(b.id);
});
It worked for me, hope it helps.
Make the list into a object so instead of order = [3, 1, 9, 4]
you will have order = { 3:0, 1:1, 9:2, 4:3}
, then do the following
function ( order, objects ){
ordered_objects = []
for( var i in objects ){
object = objects[i]
ordered_objects[ order[ object.id ] ] = object
}
return ordered_objects
}
You can do it with Alasql library with simple SELECT JOIN of two arrays.
The only one thing: Alasql understands source data as array of arrays or array of objects, so you need to convert simple array to array of arrays (see Step 1)
var data1 = [ { id: 3, name:'jess' }, { id: 1, name:'abc' },
{ id: 9, name:'...' }, { id: 4, name:'alex' } ];
var data2 = [3, 1, 9, 4];
// Step 1: Convert [3,1,9,4] to [[3],[1],[9],[4]]
var data2a = data2.map(function(d){return [d]});
// Step 2: Get the answer
var res = alasql('SELECT data1.* FROM ? data1 JOIN ? data2 ON data1.id = data2.[0]',
[data1,data2a]);
Try this example at jsFiddle.
Well, the simple answer would be, "for a set of data this small, anything less costly than an infinite loop will be basically unnoticeable." But let's try to answer this "right."
There's no rhyme or reason to the order in the second array, it's just a list of foreign keys (to use SQL terminology) on the primary keys of the first array. So, thinking of them as keys, and that we want efficient lookup of those keys, a hash table (object) would probably "sort" this the quickest, in an O(n)
fashion (2*n
, really) assuming the first array is called objArray
and the second array is called keyArray
:
// Create a temporary hash table to store the objects
var tempObj = {};
// Key each object by their respective id values
for(var i = 0; i < objArray.length; i++) {
tempObj[objArray[i].id] = objArray[i];
}
// Rebuild the objArray based on the order listed in the keyArray
for(var i = 0; i < keyArray.length; i++) {
objArray[i] = tempObj[keyArray[i]];
}
// Remove the temporary object (can't ``delete``)
tempObj = undefined;
And that should do it. I can't think of any method that doesn't require two passes. (Either one after the other, like this, or by passing multiple times through the array and splice
ing out the found elements, which can get costly with backwards-sorted data, for instance.)