How do I sort an array of objects based on the ordering of another array?

前端 未结 8 505
滥情空心
滥情空心 2020-11-28 12:41

I have a list of objects:

[ { id: 4, name:\'alex\' }, { id: 3, name:\'jess\' }, { id: 9, name:\'...\' }, { id: 1, name:\'abc\' } ]

I have a

相关标签:
8条回答
  • 2020-11-28 13:20

    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.

    0 讨论(0)
  • 2020-11-28 13:25

    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);​
    
    0 讨论(0)
  • 2020-11-28 13:31

    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.

    0 讨论(0)
  • 2020-11-28 13:35

    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
    }
    
    0 讨论(0)
  • 2020-11-28 13:36

    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.

    0 讨论(0)
  • 2020-11-28 13:37

    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 spliceing out the found elements, which can get costly with backwards-sorted data, for instance.)

    0 讨论(0)
提交回复
热议问题