Lodash基于外部数组的排序集合

Posted

技术标签:

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

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

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

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

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

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

【问题讨论】:

你用的是什么语言? 我正在使用 javascript @silintzir 请考虑accepting any of the answers,它对您的帮助最大。 【参考方案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'
];

    先创建一个索引对象,用_.reduce,像这样

    var indexObject = _.reduce(data2, function(result, currentObject) 
        result[currentObject.guid] = currentObject;
        return result;
    , );
    

    然后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;

【讨论】:

以上是关于Lodash基于外部数组的排序集合的主要内容,如果未能解决你的问题,请参考以下文章

从对象集合中的项目的 lodash.find 方法获取未定义

如何使用 Lodash.js 对集合/数组进行反透视?

Lodash / javascript:比较两个集合并返回差异[重复]

使用 lodash 在集合中进行通配符搜索

如何使用 lodash _.filter() 过滤 Firestore 集合?

数组转换为集合进行排序,集合数组自定义排序