【问题标题】:Lodash sort collection based on external arrayLodash基于外部数组的排序集合
【发布时间】:2015-04-27 11:49:22
【问题描述】:

我有一个带有如下键的数组:

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

以及一个在每个对象中都有这些键的集合,如下所示:

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

有没有一种快速的方法可以根据第一个数组中键的顺序对集合进行排序?

【问题讨论】:

标签: javascript arrays collections underscore.js lodash


【解决方案1】:
var sortedCollection = _.sortBy(collection, function(item){
  return firstArray.indexOf(item.guid)
});

【讨论】:

  • @silintzir 您在问题中要求a fast way to sort the collection。但这不是一个快速的方法,如果你真的指的是运行时性能。
  • 这很完美,是我找到的最优雅的解决方案
  • 简单的解决方案!
  • 是保留与第一个数组中没有元素匹配的集合元素还是删除它们?
  • 基于多键排序最有效的方法是什么?
【解决方案2】:

如果您想将不匹配的元素放在 sortedCollection 的末尾而不是开头,这只是对已接受答案的简单添加:

const last = collection.length;

var sortedCollection = _.sortBy(collection, function(item) {
  return firstArray.indexOf(item.guid) !== -1? firstArray.indexOf(item.guid) : last;
});

【讨论】:

    【解决方案3】:

    输入:

    var data1 = ['129asg', '39342aa'];
    var data2 = [{
        guid: '39342aa',
        name: 'John'
    }, {
        guid: '129asg',
        name: 'Mary'
    }];
    
    1. 先创建一个索引对象,用_.reduce,像这样

      var indexObject = _.reduce(data2, function(result, currentObject) {
          result[currentObject.guid] = currentObject;
          return result;
      }, {});
      
    2. 然后map第一个数组的项目与来自indexObject的对象,像这样

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

    输出

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

    注意:如果你想对这么多的对象进行排序,这种方法会非常有效,因为它会减少第二个数组中的线性查找,这会使整个逻辑运行在 O( M * N) 时间复杂度。

    【讨论】:

      【解决方案4】:

      您可以使用indexBy()at() 对您的收藏进行排序。优点是简洁的代码和性能。在这里使用sortBy() 可以解决问题,但是您的外部数组已经排序了:

      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' ]
      

      使用at(),您可以遍历已排序的外部集合,从源collection 构建一个新集合。源集合已使用indexBy() 转换为对象。您这样做 at() 对每个 ids 具有基于密钥的访问权限。

      【讨论】:

      • 这个答案应该随着lodash方式和功能的变化而更新。
      【解决方案5】:

      这是高效且干净的方式:

      (导入 lodash identitysortBy):

      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;
      }
      

      或者在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;
      }
      

      【讨论】:

        猜你喜欢
        • 2019-06-12
        • 2020-04-14
        • 2022-07-22
        • 1970-01-01
        • 2015-07-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多