Sort an array of objects based on another array of ids

后端 未结 10 2116
故里飘歌
故里飘歌 2020-11-28 16:27

I have 2 arrays

a = [2,3,1,4]
b = [{id: 1}, {id: 2}, {id: 3}, {id: 4}]

How do I get b sorted based on a? My desir

10条回答
  •  旧巷少年郎
    2020-11-28 16:57

    Ramda really shines for these types of problems.

    Where the size of the data is small, we can use a simple reduce function, and indexOf helper.

    // match id of object to required index and insert
    var sortInsert = function (acc, cur) {
      var toIdx = R.indexOf(cur.id, a);
      acc[toIdx] = cur;
      return acc;
    };
    
    // point-free sort function created
    var sort = R.reduce(sortInsert, []);
    
    // execute it now, or later as required
    sort(b);
    // [ { id: 2 }, { id: 3 }, { id: 1 }, { id: 4 } ]
    

    This works well for small(ish) data sets but the indexOf operation on every iteration through the reduction is inefficient for large data sets.

    We can remedy this by tackling the problem from the other side, lets use groupBy to group our objects by their id, thus creating a dictionary lookup (much better!). We can then simply map over the required indexes and transform them to their corresponding object at that position.

    And here is the solution using this approach:

    var groupById = R.groupBy(R.prop('id'), b);
    
    var sort = R.map(function (id) {
        return groupById[id][0];
    });
    
    sort(a);
    // [ { id: 2 }, { id: 3 }, { id: 1 }, { id: 4 } ]
    

    Finally, this is yet another solution, which is very succinct:

    R.sortBy(R.pipe(R.prop('id'), R.indexOf(R.__, a)))(b);
    // [ { id: 2 }, { id: 3 }, { id: 1 }, { id: 4 } ]
    

    I love the way you can compose functions with behaviour and separate the algorithm from the data upon which it acts using Ramda. You end up with very readable, and easy to maintain code.

提交回复
热议问题