GtAntoine
GtAntoine

Reputation: 1089

Filter array of objects with another array of objects

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 ?

Upvotes: 77

Views: 125423

Answers (12)

Ashdeep Singh
Ashdeep Singh

Reputation: 128

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

Upvotes: 0

Triguna
Triguna

Reputation: 574

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.

Upvotes: 43

Ruben
Ruben

Reputation: 9186

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.

Upvotes: 17

Jewel K Wilson
Jewel K Wilson

Reputation: 53

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)

Upvotes: 1

Rintu Raj
Rintu Raj

Reputation: 1

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

Upvotes: 0

Andy
Andy

Reputation: 63514

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

Upvotes: 147

Tabares
Tabares

Reputation: 4335

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

Upvotes: 25

Vladimir
Vladimir

Reputation: 342

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

Upvotes: 6

benny
benny

Reputation: 315

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

Upvotes: 3

Djk
Djk

Reputation: 26

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.

Upvotes: 1

Renato Galvones
Renato Galvones

Reputation: 555

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

Upvotes: 14

Magicprog.fr
Magicprog.fr

Reputation: 4100

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

Upvotes: 5

Related Questions