简体   繁体   English

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

[英]JavaScript filter array by data from another

I have an array object:我有一个数组对象:

[
    { id:1, name: 'Pedro'},
    { id:2, name: 'Miko'},
    { id:3, name: 'Bear'},
    { id:4, name: 'Teddy'},
    { id:5, name: 'Mouse'}
]

And I have an array with ids [1, 3, 5],我有一个 ID 为 [1, 3, 5] 的数组,

How can I filter the array object to leave records only with id's from the second one?如何过滤数组对象以仅保留第二个 id 的记录?

If Array.includes() is supported, you can use it with Array.filter() to get the items:如果支持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);

If includes is not supported, you can use Array.indexOf() instead:如果不支持包含,您可以使用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);

Maybe take a Array.prototype.reduce in combination with an Array.prototype.some .也许将Array.prototype.reduceArray.prototype.some结合使用。 This keeps the order of the given array need .这将保持给定数组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>');

To keep the order of data you can use Array.prototype.filter :为了保持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>');

In case the data set is small, you are ok with any of the offered solution (ones that use indexOf).如果数据集很小,您可以使用任何提供的解决方案(使用 indexOf 的解决方案)。

However, these solutions are O(n^2) ones, therefore, given the data set big enough, the lag can become noticeable.然而,这些解决方案是 O(n^2) 的,因此,如果数据集足够大,滞后会变得明显。 In this case, you should build an index prior to selecting elements.在这种情况下,您应该在选择元素之前构建索引。

Example:例子:

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;
    });
}

And some benchmarking can be tested here .一些基准测试可以在这里进行测试。

You can use a for loop on the object array and check hasOwnProperty in another for loop for each ids in [1,3,5] (break out of the loop once an id found).您可以在对象数组上使用 for 循环,并在另一个 for 循环中为[1,3,5]每个 id 检查hasOwnProperty (一旦找到 id 就跳出循环)。 (And break out of the bigger for-loop once all ids are found) If your array object is ordered (eg elements sorted from smallest id to biggest id) and so are your list, this solution should be quite efficient. (一旦找到所有 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;
}

or use array.splice( i, 1 );或使用array.splice( i, 1 ); if you don't want an empty slot.如果你不想要一个空插槽。

Using filter and indexOf will do the trick:使用filterindexOf可以解决问题:

var filteredArray = dataArray.filter(function(obj) {
  return idsArray.indexOf(obj.id) > -1;
});

However, indexOf has linear performance, and it will be called lots of times.但是, indexOf具有线性性能,并且会被多次调用。

In ES6 you can use a set instead, whose has call has sublinear performance (on average):在 ES6 中,您可以使用 set 代替,其has调用具有次线性性能(平均):

var idsSet = new Set(idsArray),
    filteredArray = dataArray.filter(obj => idsSet.has(obj.id));

Assuming the toString method of your ids is injective, you can achieve something similar in ES5:假设你的 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];
});

You can use the filter method on your Array:您可以在 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
    });
}

See it in action in this JSFiddle .在这个 JSFiddle 中查看它的实际效果

Or if you are using jQuery, another option may be:或者,如果您使用的是 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