How to filter array when object key value is in array
Asked Answered
Z

8

71

I have an array model, as below:

records:[{
    "empid":1,
    "fname": "X",
    "lname": "Y"
},
{
    "empid":2,
    "fname": "A",
    "lname": "Y"
},
{
    "empid":3,
    "fname": "B",
    "lname": "Y"
},
{
    "empid":4,
    "fname": "C",
    "lname": "Y"
},
{
    "empid":5,
    "fname": "C",
    "lname": "Y"
}
]

Now I have an array of empid's [1,4,5].

So now, I need to filter the first array, which contains all the keys in my second.

Output:

records:[{
    "empid":1,
    "fname": "X",
    "lname": "Y"
},
{
    "empid":4,
    "fname": "C",
    "lname": "Y"
},
{
    "empid":5,
    "fname": "C",
    "lname": "Y"
}
]

I can do this using a forEach loop in angular, but as I have more than 100 records in my model object, I need a way to handle this in a much cleaner way.

I'm thinking of creating a custom filter, but what is your take on it? (If yes, please provide sample code to achieve this).

Zipporah answered 5/3, 2016 at 17:48 Comment(4)
are the data and ids sorted?Butadiene
No, data is not sorted.. Aravindsamy's solution looks good.. Thank you guys for quick response..Zipporah
Almost duplicate of javascript - How to filter object array based on attributes? - Stack Overflow -- although in this case the condition is a little more complicated (with includes)'llZashin
how you get this result [1,4,5]Pavia
A
95

You can do it with Array.prototype.filter(),

var data = { records : [{ "empid": 1, "fname": "X", "lname": "Y" }, { "empid": 2, "fname": "A", "lname": "Y" }, { "empid": 3, "fname": "B", "lname": "Y" }, { "empid": 4, "fname": "C", "lname": "Y" }, { "empid": 5, "fname": "C", "lname": "Y" }] }
var empIds = [1,4,5]
var filteredArray = data.records.filter(function(itm){
  return empIds.indexOf(itm.empid) > -1;
});

filteredArray = { records : filteredArray };

If​ the ​callBack​ returns a ​true​ value, then the ​itm​ passed to that particular callBack will be filtered out. You can read more about it here.​​​​​​

Allnight answered 5/3, 2016 at 17:53 Comment(3)
This is really simple and easy @Rajaprabhu,but any information related to performance while doing this on large data(about 500-1000) length array,Zipporah
@KrishnaAditya It is very similar to for loop, internally data will be iterated by using for loops, But in an efficient way. This makes code more readable and maintainable.Allnight
Maybe you can look at javascript - Filter array of objects with another array of objects - Stack Overflow for a different approach.Moise
C
68

In 2019 using ES6:

const ids = [1, 4, 5],
  data = {
    records: [{
      "empid": 1,
      "fname": "X",
      "lname": "Y"
    }, {
      "empid": 2,
      "fname": "A",
      "lname": "Y"
    }, {
      "empid": 3,
      "fname": "B",
      "lname": "Y"
    }, {
      "empid": 4,
      "fname": "C",
      "lname": "Y"
    }, {
      "empid": 5,
      "fname": "C",
      "lname": "Y"
    }]
  };


data.records = data.records.filter( i => ids.includes( i.empid ) );

console.info( data );
Courtland answered 17/5, 2019 at 7:57 Comment(2)
Some words of explanation would increase the value of your answer immensely for JavaScript beginners. ;)Horodko
@Andreas, He basically creates a temporary array (ids) that he wants to use as a filter criteria. Then he uses the filter function on the data.records array and says "remove all items that do not have an ID matching one of those in the temporary array", and reassigns this to the data.records array. The key functions here are Array.filter and Array.includes.Embargo
B
3

This is a fast solution with a temporary object.

var records = [{ "empid": 1, "fname": "X", "lname": "Y" }, { "empid": 2, "fname": "A", "lname": "Y" }, { "empid": 3, "fname": "B", "lname": "Y" }, { "empid": 4, "fname": "C", "lname": "Y" }, { "empid": 5, "fname": "C", "lname": "Y" }],
    empid = [1, 4, 5],
    object = {},
    result;

records.forEach(function (a) {
    object[a.empid] = a;
});

result = empid.map(function (a) {
    return object[a];
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Butadiene answered 5/3, 2016 at 17:54 Comment(1)
Yeah this even looks good. More likely as hash key look up,I will check this one as well. Thanks @NinaZipporah
M
2

You can use Array#filter function and additional array for storing sorted values;

var recordsSorted = []

ids.forEach(function(e) {
    recordsSorted.push(records.filter(function(o) {
        return o.empid === e;
    }));
});

console.log(recordsSorted);

Result:

[ [ { empid: 1, fname: 'X', lname: 'Y' } ],
  [ { empid: 4, fname: 'C', lname: 'Y' } ],
  [ { empid: 5, fname: 'C', lname: 'Y' } ] ]
Massimiliano answered 5/3, 2016 at 18:15 Comment(0)
P
1

Fastest way (will take extra memory):

var empid=[1,4,5]
var records = [{ "empid": 1, "fname": "X", "lname": "Y" }, { "empid": 2, "fname": "A", "lname": "Y" }, { "empid": 3, "fname": "B", "lname": "Y" }, { "empid": 4, "fname": "C", "lname": "Y" }, { "empid": 5, "fname": "C", "lname": "Y" }] ;

var empIdObj={};

empid.forEach(function(element) {
empIdObj[element]=true;
});

var filteredArray=[];

records.forEach(function(element) {
if(empIdObj[element.empid])
    filteredArray.push(element)
});
Purpura answered 5/3, 2016 at 19:6 Comment(0)
T
0

Old way of doing it. Many might hate this way of doing but i still many time find this is still better in my perspective.

Input:

var records = [{
    "empid":1,
    "fname": "X",
    "lname": "Y"
},
{
    "empid":2,
    "fname": "A",
    "lname": "Y"
},
{
    "empid":3,
    "fname": "B",
    "lname": "Y"
},
{
    "empid":4,
    "fname": "C",
    "lname": "Y"
},
{
    "empid":5,
    "fname": "C",
    "lname": "Y"
}
]

var newArr = [1,4,5];

Code:

var newObj = [];
for(var a = 0 ; a < records.length ; a++){
 if(newArr.indexOf(records[a].empid) > -1){
  newObj.push(records[a]);
 }
}

The indexOf() method returns the first index at which a given element can be found in the array, or -1 if it is not present.

Reference - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf

Output:

[{
    "empid": 1,
    "fname": "X",
    "lname": "Y"
}, {
    "empid": 4,
    "fname": "C",
    "lname": "Y"
}, {
    "empid": 5,
    "fname": "C",
    "lname": "Y"
}]
Thiel answered 16/2, 2021 at 14:10 Comment(0)
D
0
var records = [{
 "empid":1,
 "fname": "X",
 "lname": "Y"
},
{
 "empid":2,
 "fname": "A",
 "lname": "Y"
}

]


let search="A"
 
let values= Result.filter(item =>
     keys.some(key => 
         String(item[key]).toLowerCase().includes(search.toLowerCase()) 
     )
 );

multikey search in object Array eg.(empid,fname,lname)

Doehne answered 10/9, 2021 at 10:44 Comment(2)
Please add further details to expand on your answer, such as working code or documentation citations.Invigilate
You could use the javascript/html/css snippet accessible with CTRL+M to make the code able to be run.Fluellen
A
-1

In case you have key value pairs in your input array, I used:

.filter(
          this.multi_items[0] != null && store.state.isSearchBox === false
            ? item =>
                _.map(this.multi_items, "value").includes(item["wijknaam"])
            : item => item["wijknaam"].includes("")
        );

where the input array is multi_items as: [{"text": "bla1", "value": "green"}, {"text": etc. etc.}]

_.map is a lodash function.

Athalla answered 1/11, 2019 at 16:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.