2013-02-27 92 views
20

我想过滤一个基于另一个对象的数组。共同财产编号id。 我不确定过滤器+每个都是执行此操作或映射缩减的最佳方法。无论如何,下面的代码不起作用,因为out是空列表。underscore.js过滤一个基于另一个对象的数组

var aaa = [ 
    {name: "AAA", id: 845}, 
    {name: "BBB", id: 839}, 
    {name: "CCC", id: 854} 
]; 
var bbb = [ 
    {id: 839}, 
    {id: 854} 
]; 

var out = _.filter(aaa, function(val){ 
    return _.each(this, function(val2){ 
     return val['id'] === val2['id'] 
    }); 
}, bbb); 

回答

37

只需创建一个有效ID “设置” 和使用 “设置” 做滤波:

var aaa = [ 
    {name: "AAA", id: 845}, 
    {name: "BBB", id: 839}, 
    {name: "CCC", id: 854} 
]; 
var bbb = [ 
    {id: 839}, 
    {id: 854} 
]; 

var ids = {}; 
_.each(bbb, function (bb) { ids[bb.id] = true; }); 

var out = _.filter(aaa, function (val) { 
    return ids[val.id]; 
}, bbb); 

灌装ids快,它在N * amortized O(1)即O(n)。过滤同样适用。

如果在内循环中使用each(…),则会有O(n²)。对于更大的数据集,这将变得非常缓慢。另外,嵌套使代码更难以第一眼看懂。

见该代码在行动剪断:http://jsfiddle.net/SMtX5/

+1

thans为解释和推理背后。 – bsr 2013-02-27 20:45:33

2

您可以使用_.some(list, [iterator], [context])

它返回如果任何在列表值的传递迭代真相的考验。

var out = _.filter(aaa, function(val){ 
    return _.some(this,function(val2){ 
     return val2['id'] === val['id']; 
    }); 
}, bbb); 

这里是jsfiddle。 http://jsfiddle.net/h98ej/

+0

基于接受的答案,这个例程比所接受的要快得多吗? – 2016-10-17 16:03:27

15

可以使用_.find过滤:

_.filter(aaa, function(a){ 
    return _.find(bbb, function(b){ 
     return b.id === a.id; 
    }); 
}); 
1
bbb = bbb.map(_ => _.id) && aaa.filter(_ => bbb.indexOf(_.id) > -1) 

你只需要纯JS数组函数做假设你的使用情况。

相关问题