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 have array with ids [1,3,5]

How to filter array object to leave records only with id's from second one? Thanks!

Answers:

Answer

If Array.includes() is supported, you can use it with Array.filter() to get the items:

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:

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

Answer

Maybe take a Array.prototype.reduce in combination with an Array.prototype.some. This keeps the order of the given array 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:

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

Answer

In case the data set is small, you are ok with any of the offered solution (ones that use indexOf).

However, these solutions are O(n^2) ones, therefore, given the data set big enough, the lag can become noticeable. 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.

Answer

Or if you are using jQuery, another option may be:

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

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). (And break out of the bigger for-loop once all ids are found) If your array object is ordered (e.g. elements sorted from smallest id to biggest id) and so are your list, this solution should be quite efficient.

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 ); if you don't want an empty slot.

Answer

Using filter and indexOf will do the trick:

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.

In ES6 you can use a set instead, whose has call has sublinear performance (on average):

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:

var idsHash = Object.create(null);
idsArray.forEach(function(id) {
  idsHash[id] = true;
});
var filteredArray = dataArray.filter(function(obj) {
  return idsHash[obj.id];
});
Answer

You can use the filter method on your Array:

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.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.