简体   繁体   中英

Javascript - generic solution to filter an array of objects based on properties of any depth present in a filter object

How can I filter a list of objects based on properties of any depth present in a filter object generically - without knowing the name of the properties in advance?

Given the following example list:

var list = [
{ name: 'Alice', address: { zip: '10000', street: '71 Pilgrim Avenue' } },
{ name: 'Bob', address: { zip: '20000', street: '44 Shirley Ave' } },
{ name: 'Charlie', address: { zip: '30000', street: '4 Goldfield Rd' } },
]

If I have the following filter object, I would like returned the objects in the array matching this filter.

var filter = {
 address: { zip: '10000' }
}

The return in this case should be:

[{ name: 'Alice', address: { zip: '10000', street: '71 Pilgrim Avenue' } }]

I've attempted to iterate over the properties of the objects with the Object.keys() function, but the problem I'm having is that the Object.keys function are not only returning the properties but also the property values as an array.

Edit: updated the example date with another field to make it clear that any level can have multiple properties.

You can write a recursive function that checks whether one object "contains" another:

const compare = r => l => (typeof l === "object" ? contains(r)(l) : l === r);
const contains = r => l =>
  Object.keys(r).every(k => l.hasOwnProperty(k) && compare(r[k])(l[k]));

var list = [
  {
    name: "Alice",
    address: {
      zip: "10000"
    }
  },
  {
    name: "Bob",
    address: {
      zip: "20000"
    }
  },
  {
    name: "Charlie",
    address: {
      zip: "30000"
    }
  }
];

var filter = {
  address: { zip: "10000" }
};

console.log(list.filter(contains(filter)));
// [{"name":"Alice","address":{"zip":"10000"}}]

I am assuming you the objects you are filtering can only contain "plain" nested objects or primitive values that can directly be compared. If you can have more complicated values like arrays, you'll need to add more cases in the compare function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM