繁体   English   中英

JavaScript 按来自另一个的数据过滤数组

[英]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.reduceArray.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 ); 如果你不想要一个空插槽。

使用filterindexOf可以解决问题:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM