67

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

danik0011
  • 72
  • 10
krsnaadi
  • 745
  • 1
  • 5
  • 9
  • are the data and ids sorted? – Nina Scholz Mar 05 '16 at 17:55
  • No, data is not sorted.. Aravindsamy's solution looks good.. Thank you guys for quick response.. – krsnaadi Mar 05 '16 at 18:01
  • Almost duplicate of [javascript - How to filter object array based on attributes? - Stack Overflow](https://stackoverflow.com/questions/2722159/how-to-filter-object-array-based-on-attributes) -- although in this case the condition is a little more complicated (with `includes`)'ll – user202729 Feb 16 '21 at 10:11
  • how you get this result [1,4,5] – samran Sep 09 '21 at 15:18

8 Answers8

93

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.​​​​​​

Preactive
  • 310
  • 1
  • 13
Rajaprabhu Aravindasamy
  • 66,513
  • 17
  • 101
  • 130
  • This is really simple and easy @Rajaprabhu,but any information related to performance while doing this on large data(about 500-1000) length array, – krsnaadi Mar 05 '16 at 18:05
  • 1
    @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. – Rajaprabhu Aravindasamy Mar 05 '16 at 18:08
  • Maybe you can look at [javascript - Filter array of objects with another array of objects - Stack Overflow](https://stackoverflow.com/a/31005792/2057854) for a different approach. – AndyDaSilva52 Jun 10 '22 at 00:51
64

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 );
Tim Elsass
  • 966
  • 7
  • 9
  • 3
    Some words of explanation would increase the value of your answer immensely for JavaScript beginners. ;) – Andreas Aug 10 '20 at 09:56
  • 1
    @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. – Tyler Aug 24 '22 at 06:52
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>');
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Yeah this even looks good. More likely as hash key look up,I will check this one as well. Thanks @Nina – krsnaadi Mar 05 '16 at 18:15
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' } ] ]
isvforall
  • 8,768
  • 6
  • 35
  • 50
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)
});
me_astr
  • 922
  • 1
  • 14
  • 21
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"
}]
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)

manjit singh
  • 21
  • 1
  • 4
  • 1
    Please add further details to expand on your answer, such as working code or documentation citations. – Community Sep 10 '21 at 11:42
  • You could use the `javascript/html/css snippet` accessible with `CTRL+M` to make the code able to be run. – Paulo Sep 10 '21 at 12:17
-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.