[英]JavaScript filter array by data from another
我有一个数组对象:
[
{ id:1, name: 'Pedro'},
{ id:2, name: 'Miko'},
{ id:3, name: 'Bear'},
{ id:4, name: 'Teddy'},
{ id:5, name: 'Mouse'}
]
我有一个 ID 为 [1, 3, 5] 的数组,
如何过滤数组对象以仅保留第二个 id 的记录?
如果支持Array.includes()
则可以将其与Array.filter()
一起使用以获取项目:
const array = [ { id: 1, name: 'Pedro'}, { id: 2, name: 'Miko'}, { id: 3, name: 'Bear'}, { id: 4, name: 'Teddy'}, { id: 5, name: 'Mouse'} ]; const filterArray = [1,3,5]; const result = array.filter(({ id }) => filterArray.includes(id)); console.log(result);
如果不支持包含,您可以使用Array.indexOf()
代替:
var array = [ { id: 1, name: 'Pedro'}, { id: 2, name: 'Miko'}, { id: 3, name: 'Bear'}, { id: 4, name: 'Teddy'}, { id: 5, name: 'Mouse'} ]; var filterArray = [1,3,5]; var result = array.filter(function(item) { return filterArray.indexOf(item.id) !== -1; }); console.log(result);
也许将Array.prototype.reduce
与Array.prototype.some
结合使用。 这将保持给定数组need
的顺序。
var data = [ { id: 3, name: 'Bear' }, { id: 4, name: 'Teddy' }, { id: 5, name: 'Mouse' }, { id: 1, name: 'Pedro' }, { id: 2, name: 'Miko' }, ], need = [1, 3, 5], filtered = need.reduce(function (r, a) { data.some(function (el) { return a === el.id && r.push(el); }); return r; }, []); document.write('<pre>' + JSON.stringify(filtered, 0, 4) + '</pre>');
为了保持data
的顺序,您可以使用Array.prototype.filter
:
var data = [ { id: 3, name: 'Bear' }, { id: 4, name: 'Teddy' }, { id: 5, name: 'Mouse' }, { id: 1, name: 'Pedro' }, { id: 2, name: 'Miko' }, ], need = [1, 3, 5], filtered = data.filter(function (a) { return ~need.indexOf(a.id); }); document.write('<pre>' + JSON.stringify(filtered, 0, 4) + '</pre>');
如果数据集很小,您可以使用任何提供的解决方案(使用 indexOf 的解决方案)。
然而,这些解决方案是 O(n^2) 的,因此,如果数据集足够大,滞后会变得明显。 在这种情况下,您应该在选择元素之前构建索引。
例子:
function filterFast(data, ids) {
var index = ids.reduce(function(a,b) {a[b] = 1; return a;}, {});
return data.filter(function(item) {
return index[item.id] === 1;
});
}
一些基准测试可以在这里进行测试。
您可以在对象数组上使用 for 循环,并在另一个 for 循环中为[1,3,5]
每个 id 检查hasOwnProperty
(一旦找到 id 就跳出循环)。 (一旦找到所有 id,就跳出更大的 for 循环)如果您的数组对象是有序的(例如,元素从最小 id 到最大 id 排序),那么您的列表也是如此,这个解决方案应该非常有效。
var c = 0;
for(var i =0; i< objects.length; i++){
for(var v =0; v< list.length; v++)
if(objects[i].hasOwnProperty(list[v])){
delete objects[i]; c++; break;
}
if(c===list.length) break;
}
或使用array.splice( i, 1 );
如果你不想要一个空插槽。
使用filter
和indexOf
可以解决问题:
var filteredArray = dataArray.filter(function(obj) {
return idsArray.indexOf(obj.id) > -1;
});
但是, indexOf
具有线性性能,并且会被多次调用。
在 ES6 中,您可以使用 set 代替,其has
调用具有次线性性能(平均):
var idsSet = new Set(idsArray),
filteredArray = dataArray.filter(obj => idsSet.has(obj.id));
假设你的 ids 的toString
方法是单射的,你可以在 ES5 中实现类似的东西:
var idsHash = Object.create(null);
idsArray.forEach(function(id) {
idsHash[id] = true;
});
var filteredArray = dataArray.filter(function(obj) {
return idsHash[obj.id];
});
您可以在 Array 上使用filter 方法:
var data = [
{ id:1, name: 'Pedro'},
{ id:2, name: 'Miko'},
{ id:3, name: 'Bear'},
{ id:4, name: 'Teddy'},
{ id:5, name: 'Mouse'}
];
var ids = [1, 3, 5];
var filteredData = filterData(data, 'id', ids[1]);
function filterData(data, prop, values) {
return data.filter(function(item) {
return ~values.indexOf(item[prop]); // ~ returns 0 if indexOf returns -1
});
}
在这个 JSFiddle 中查看它的实际效果。
或者,如果您使用的是 jQuery,另一种选择可能是:
var arr1 = [1, 3, 5],
arr2 = [{ id: 1, name: 'Pedro' },
{ id: 2, name: 'Miko' },
{ id: 3, name: 'Bear' },
{ id: 4, name: 'Teddy' },
{ id: 5, name: 'Mouse' }],
filtered = $.grep(arr2, function (item) {
if (arr1.indexOf(item.id) > -1) {
return true;
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.