73

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 ?

Community
  • 1
  • 1
GtAntoine
  • 1,049
  • 1
  • 8
  • 12

11 Answers11

144

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);
Andy
  • 61,948
  • 13
  • 68
  • 95
  • 1
    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: https://playcode.io/586682/ – TMA Apr 27 '20 at 08:29
  • 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))` – Ivar Dec 20 '21 at 11:13
  • 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? – Anake.me Mar 05 '23 at 05:43
  • @Anake.me you should ask a new question. Make sure you include input/expected output, and code for a [mcve]. – Andy Mar 05 '23 at 12:57
36

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(ad => 
             filterData.every(fd => fd.userid !== md.userid));

result contains all masterData except filterData.

Triguna
  • 504
  • 6
  • 13
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

Tabares
  • 4,083
  • 5
  • 40
  • 47
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.

Joel Carneiro
  • 3,287
  • 3
  • 16
  • 20
Ruben
  • 8,956
  • 14
  • 63
  • 102
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);
Renato Galvones
  • 533
  • 1
  • 3
  • 14
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") )
Vladimir
  • 342
  • 1
  • 8
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

Magicprog.fr
  • 4,072
  • 4
  • 26
  • 35
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);
benny
  • 315
  • 1
  • 7
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.

Djk
  • 26
  • 2
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)
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);
Nisanth Reddy
  • 5,967
  • 1
  • 11
  • 29