2013-02-27 2 views
20

Я пытаюсь отфильтровать массив объектов на основе другого. Общее свойство id 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

Просто создать «установить» действительных идентификаторов и использовать это «набор», чтобы сделать фильтрацию:

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 быстро, это в п * amortized O (1), т.е. O (n). То же самое относится к фильтрации.

Если вы используете each(…) во внутреннем цикле, у вас будет O (n²). Для больших наборов данных это будет очень медленным. Кроме того, дополнительное вложение делает код более трудным для чтения/понимания с первого взгляда.

Смотрите, что код надрезается в действии: http://jsfiddle.net/SMtX5/

+1

thans для объяснения и обоснования позади. – bsr

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

Основываясь на принятом ответе, намного быстрее это процедура против того, что было принято? –

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, чтобы сделать это при условии, ваш случай использования.

Смежные вопросы