[英]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.