Filter array of objects with another array of objects
Asked Answered
C

12

77

This question is similar to this one Jquery filter array of object with loop but this time I need to do the filter with an array of objects.

Exemple:

I have an array of objects like this:

myArray = [
{
    userid: "100", 
    projectid: "10",
    rowid: "0"
},
{
    userid: "101", 
    projectid: "11",
    rowid: "1"},
{    
    userid: "102", 
    projectid: "12",
    rowid: "2"},
{    
    userid: "103", 
    projectid: "13",
    rowid: "3"
},
{    
    userid: "101", 
    projectid: "10",
    rowid: "4"
}
...]

I want to filter it with an array like this:

myFilter = [
{
    userid: "101", 
    projectid: "11"
},
{
    userid: "102", 
    projectid: "12"
},
{
    userid: "103", 
    projectid: "11"
}]

and return this (the userid and the projectid in myFilter need to match the userid and the projectid in myArray):

myArrayFiltered = [
{
    userid: "101", 
    projectid: "11",
    rowid: "1"
},
{
    userid: "102", 
    projectid: "12",
    rowid: "2"
}]

How can I do that ?

Corriveau answered 23/6, 2015 at 14:19 Comment(0)
R
14
var filtered = [];

for(var arr in myArray){
   for(var filter in myFilter){
       if(myArray[arr].userid == myFilter[filter].userid && myArray[arr].projectid == myFilter[filter].projectid){
          filtered.push(myArray[arr].userid);
         }
   }
}
console.log(filtered);
Refugiorefulgence answered 23/6, 2015 at 14:36 Comment(0)
M
147

You can put a couple of array methods to use here - filter and some. They're available in all recent browsers, and there are polyfills available for the older browsers.

const myArray = [{ userid: "100", projectid: "10", rowid: "0" }, { userid: "101", projectid: "11", rowid: "1"}, { userid: "102", projectid: "12", rowid: "2" }, { userid: "103", projectid: "13", rowid: "3" }, { userid: "101", projectid: "10", rowid: "4" }];
const myFilter = [{ userid: "101", projectid: "11" }, { userid: "102", projectid: "12" }, { userid: "103",  projectid: "11"}];

const myArrayFiltered = myArray.filter((el) => {
  return myFilter.some((f) => {
    return f.userid === el.userid && f.projectid === el.projectid;
  });
});

console.log(myArrayFiltered);
Mainz answered 23/6, 2015 at 14:34 Comment(4)
Hi @Andy, i am doing the same thing with the just one condition change about not equal to !== but that is not working in my case. So is there any other method to work with the not equal to condition ? Check my live example over here: playcode.io/586682Remove
Depending on your preference, you can also make the statement a bit more concise: myArray.filter(el => myFilter.some(f => f.userid === el.userid && f.projectid === el.projectid))Terminator
How would this work if you had an array for rowid? (E.g. rowid: ["1", "2"] and another array matches at least ONE of those) I have used the code above to successfully filter difficulty in my project as it is only one value, however I have an array of tags that I wish to filter. So if my array1 contains ANY of the tags in array2, output a new array of results?Overmeasure
@Overmeasure you should ask a new question. Make sure you include input/expected output, and code for a minimal reproducible example.Mainz
Y
42

In response to Andy answer above, which I believe should be marked now as answer., if you are looking for exact opposite behavior, use every with negation, something like this.

const result = masterData.filter(md => 
             filterData.every(fd => fd.userid !== md.userid));

result contains all masterData except filterData.

Yon answered 16/10, 2020 at 19:14 Comment(1)
AMAZING! Works as expected and gave me exactly what I needed so fast! THANKS!!!Bisectrix
S
25

With Ecma script 6.

const myArrayFiltered = myArray.filter( el => {
  return myfilter.some( f => {
    return f.userid === el.userid && f.projectid === el.projectid;
  });
});

Function:

const filterObjectArray = (arr, filterArr) => (
    arr.filter( el =>
        filterArr.some( f =>
            f.userid === el.userid && f.projectid === el.projectid
        )
    )
);

console.log(filterObjectArray(myArray, myFilter))

Link to example

Stig answered 17/10, 2017 at 21:32 Comment(1)
The first part of this is really just a duplicate of the most up-voted answer from 2 years prior.Irisation
T
17

based on @Renato his answer, but shorter:

const myArray = [{ userid: "100", projectid: "10", rowid: "0" }, ...];
const myFilter = [{ userid: "101", projectid: "11" }, ...];

const data = myArray.filter((arrayEl) =>
  myFilter.some((filterEl) => filterEl.userid === arrayEl.userid && filterEl.projectid === arrayEl.projectid)
);

The myFilter.some expression checks if there is at least one element in the myFilter array which has the condition we set (filterEl.userid === arrayEl.userid && filterEl.projectid === arrayEl.projectid)

If there is one, it returns true and the myArray.filter will keep that entry on the resulting array, otherwise, it is filtered.

Tevis answered 18/12, 2019 at 10:16 Comment(0)
R
14
var filtered = [];

for(var arr in myArray){
   for(var filter in myFilter){
       if(myArray[arr].userid == myFilter[filter].userid && myArray[arr].projectid == myFilter[filter].projectid){
          filtered.push(myArray[arr].userid);
         }
   }
}
console.log(filtered);
Refugiorefulgence answered 23/6, 2015 at 14:36 Comment(0)
O
6

This code will match with not only by userid and projectid but with all properties of myFilter[j].

var filtered = myArray.filter(function(i){
    return myFilter.some(function(j){
        return !Object.keys(j).some(function(prop){
            return i[prop] != j[prop];
        });
    });
});

console.log(filtered);

So you can use

myFilter = [
    {
        projectid: "11"
    },
    {
        userid: "101"
    },
    {
        userid: "103",
        projectid: "13",
        rowid: "3"
    }
];

Will return

[ { userid: '101', projectid: '11', rowid: '1' },
{ userid: '103', projectid: '13', rowid: '3' },
{ userid: '101', projectid: '10', rowid: '4' } ]

Wich means all elements with

(projectid=="11") 
OR (userid=="101") 
OR ( (userid=="103") AND (projectid=="13") AND (rowid=="3") )
Openminded answered 23/6, 2015 at 14:36 Comment(0)
B
5

You need to loop over your first array, and inside this loop, loop again inside the filter.

If userid and projectid are equals, you can add the row to your filtered array:

myArray = [{
    userid: "100",
    projectid: "10",
    rowid: "0"
}, {
    userid: "101",
    projectid: "11",
    rowid: "1"
}, {
    userid: "102",
    projectid: "12",
    rowid: "2"
}, {
    userid: "103",
    projectid: "13",
    rowid: "3"
}, {
    userid: "101",
    projectid: "10",
    rowid: "4"
}];
myFilter = [{
    userid: "101",
    projectid: "11"
}, {
    userid: "102",
    projectid: "12"
}, {
    userid: "103",
    projectid: "11"
}];

function filterArray(array, filter) {
    var myArrayFiltered = [];
    for (var i = 0; i < array.length; i++) {
        for (var j = 0; j < filter.length; j++) {
            if (array[i].userid === filter[j].userid && array[i].projectid === filter[j].projectid) {
                myArrayFiltered.push(array[i]);
            }
        }
    }
    return myArrayFiltered;
}
myArrayFiltered = filterArray(myArray, myFilter);
console.log(myArrayFiltered);

JSFIDDLE

Bunce answered 23/6, 2015 at 14:35 Comment(0)
P
3

You can use jquery map, this return one array of matches:

var _filter=function(arr_data,arr_filter){
    return $.map( arr_data, function( n ) {
        for(var f in arr_filter){
            if(arr_filter[f].userid == n.userid && arr_filter[f].projectid == n.projectid){
                return n;
            }
        }
    });
}
var resp = _filter(myArray,myFilter);
console.log(resp);
Psycho answered 23/6, 2015 at 14:59 Comment(0)
G
1

If at all a filter like this is required I would propose to create a dictionary (object) whose key is hash of attributes which defines a match (in this case userid & projectid) that way you need to iterate over 1st dict(haystack) to check if key is available in 2nd dict (needle). Hope this helps.

Garlinda answered 23/6, 2015 at 14:36 Comment(0)
D
1

if you need negation for the same

const masterData = [
{
    userid: "101",
    projectid: "11",
    rowid: "1"
},
{
    userid: "101",
    projectid: "18",
    rowid: "1"
},
{
    userid: "101",
    projectid: "19",
    rowid: "1"
},{
    userid: "102",
    projectid: "12",
    rowid: "2"
}, {
    userid: "109",
    projectid: "10",
    rowid: "4"
}];
const filterData = [
{
    userid: "101",
    projectid: "11"
},
{
    userid: "102",
    projectid: "12"
},
{
    userid: "109",
    projectid: "10"
}
];




const myArrayFiltered = masterData.filter(array => filterData.every(filter => (!(filter.userid === array.userid && filter.projectid === array.projectid))));

             console.log(myArrayFiltered)
Dorty answered 25/6, 2021 at 17:1 Comment(0)
I
0
var arr1 = [
    { name:'r', type:"t1" },
    { name:'i', type:"t2" },
    { name:'n', type:"t1" }
];

var arr2 = [
    { name:'r', type:"t1" },
    { name:'i', type:"t2" },
    { name:'n', type:"t3" },
];

let output = arr1.filter(x => !arr2.find(y => (y.name == x.name && y.type == x.type)));

console.log(output);

// inverted

output = arr1.filter(x => !!arr2.find(y => (y.name == x.name && y.type == x.type)));

console.log(output);
Irk answered 12/5, 2021 at 7:47 Comment(0)
H
0

This worked for me

master.filter(md => child.some(fd => fd.id == md.id));

const master = [{
  id: 1,
  name: 'Canada'
}, {
  id: 2,
  name: 'India'
}, {
  id: 3,
  name: 'USA'
}];

const child = [1, 3]

const filtered = master.filter(m => child.some(c => c == m.id));

console.log('result', filtered);
master.filter(md => child.some(fd => fd.id == md.id));
Harmful answered 12/5 at 11:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.