Lodash sort collection based on external array

前端 未结 5 699
名媛妹妹
名媛妹妹 2020-12-30 21:01

I have an array with keys like so:

[\'asdf12\',\'39342aa\',\'12399\',\'129asg\',...] 

and a collection which has these keys in each object

相关标签:
5条回答
  • 2020-12-30 21:15

    Here is just a simple add to the accepted answer in case you want to put the unmatched elements at the end of the sortedCollection and not at the beginning:

    const last = collection.length;
    
    var sortedCollection = _.sortBy(collection, function(item) {
      return firstArray.indexOf(item.guid) !== -1? firstArray.indexOf(item.guid) : last;
    });
    
    0 讨论(0)
  • 2020-12-30 21:34
    var sortedCollection = _.sortBy(collection, function(item){
      return firstArray.indexOf(item.guid)
    });
    
    0 讨论(0)
  • 2020-12-30 21:37

    This is the efficient & clean way:

    (Import lodash identity and sortBy):

    TS:

    function sortByArray<T, U>({ source, by, sourceTransformer = identity }: { source: T[]; by: U[]; sourceTransformer?: (item: T) => U }) {
      const indexesByElements = new Map(by.map((item, idx) => [item, idx]));
      const orderedResult = sortBy(source, (p) => indexesByElements.get(sourceTransformer(p)));
      return orderedResult;
    }
    

    Or in JS:

    function sortByArray({ source, by, sourceTransformer = _.identity }) {
        const indexesByElements = new Map(by.map((item, idx) => [item, idx]));
        const orderedResult = _.sortBy(source, (p) => indexesByElements.get(sourceTransformer(p)));
        return orderedResult;
    }
    
    0 讨论(0)
  • 2020-12-30 21:41

    You can use indexBy(), and at() to sort your collection. The advantage being that concise code and performance. Using sortBy() here does the trick, but your external array is already sorted:

    var ids = [ 'cbdbac14', 'cf3526e2', '189af064' ];
    
    var collection = [
        { guid: '189af064', name: 'John' },
        { guid: 'cf3526e2', name: 'Julie' },
        { guid: 'cbdbac14', name: 'James' }
    ];
    
    _(collection)
        .indexBy('guid')
        .at(ids)
        .pluck('name')
        .value();
    // → [ 'James', 'Julie', 'John' ]
    

    Using at(), you can iterate over the sorted external collection, building a new collection from the source collection. The source collection has been transformed into an object using indexBy(). You do this so at() has key-based access for each of it's ids.

    0 讨论(0)
  • 2020-12-30 21:42

    Input:

    var data1 = ['129asg', '39342aa'];
    var data2 = [{
        guid: '39342aa',
        name: 'John'
    }, {
        guid: '129asg',
        name: 'Mary'
    }];
    
    1. First create an index object, with _.reduce, like this

      var indexObject = _.reduce(data2, function(result, currentObject) {
          result[currentObject.guid] = currentObject;
          return result;
      }, {});
      
    2. And then map the items of the first array with the objects from the indexObject, like this

      console.log(_.map(data1, function(currentGUID) {
          return indexObject[currentGUID]
      }));
      

    Output

    [ { guid: '129asg', name: 'Mary' },
      { guid: '39342aa', name: 'John' } ]
    

    Note: This method will be very efficient if you want to sort so many objects, because it will reduce the linear look-up in the second array which would make the entire logic run in O(M * N) time complexity.

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