Underscore.js фильтрует массив объектов на основе другого
Я пытаюсь отфильтровать массив объектов на основе другого. Общий идентификатор свойства id
.
Я не уверен, что фильтр + каждый - лучший способ сделать это или уменьшить карту. Во всяком случае, ниже код не работает, поскольку out
- пустой список.
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);
Ответы
Ответ 1
Просто создайте "набор" допустимых идентификаторов и используйте "set" для фильтрации:
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 * амортизируется O (1), то есть O (n). То же самое относится к фильтрации.
Если вы используете each(…)
во внутреннем цикле, у вас будет O (n²). Для больших наборов данных это будет очень медленным. Кроме того, дополнительное вложение делает код более трудным для чтения/понимания с первого взгляда.
Смотрите, что код отключен в действии: http://jsfiddle.net/SMtX5/
Ответ 2
вы можете использовать _.find
для фильтрации:
_.filter(aaa, function(a){
return _.find(bbb, function(b){
return b.id === a.id;
});
});
Ответ 3
Вы можете использовать _.some(list, [iterator], [context])
.
Возвращает true, если какое-либо из значений в списке проходит тест истины итератора.
var out = _.filter(aaa, function(val){
return _.some(this,function(val2){
return val2['id'] === val['id'];
});
}, bbb);
Вот jsfiddle. http://jsfiddle.net/h98ej/
Ответ 4
bbb = bbb.map(_ => _.id) && aaa.filter(_ => bbb.indexOf( _.id ) > -1)
Вам просто нужны чистые функции массива JS для этого, предполагая ваш прецедент.