【问题标题】:Javascript - generic solution to filter an array of objects based on properties of any depth present in a filter objectJavascript - 基于过滤器对象中存在的任何深度的属性过滤对象数组的通用解决方案
【发布时间】:2018-01-06 01:19:04
【问题描述】:

如何在不事先知道属性名称的情况下,根据过滤器对象中存在的任何深度的属性来过滤对象列表?

给出以下示例列表:

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' } },
]

如果我有以下过滤器对象,我想返回与此过滤器匹配的数组中的对象。

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

这种情况下的返回应该是:

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

我尝试使用 Object.keys() 函数迭代对象的属性,但我遇到的问题是 Object.keys 函数不仅返回属性,还返回属性值一个数组。

编辑:用另一个字段更新示例日期,以明确任何级别都可以有多个属性。

【问题讨论】:

  • Object.keys 函数只返回键,不返回值。如果您有一个简单的可重现示例,请将其添加到问题中。
  • 嗨,阿萨德。对于 Object.keys() 的行为,这是我能想到的最简单的示例:jsfiddle.net/p8956qxo - 由于这种行为,我无法编写迭代对象所有级别的函数。

标签: javascript arrays filter


【解决方案1】:

您可以编写一个递归函数来检查一个对象是否“包含”另一个对象:

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"}}]

我假设您要过滤的对象只能包含“普通”嵌套对象或可以直接比较的原始值。如果您可以有更复杂的值(例如数组),则需要在 compare 函数中添加更多案例。

【讨论】:

    猜你喜欢
    • 2019-05-29
    • 2015-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-29
    • 1970-01-01
    • 2022-11-14
    • 1970-01-01
    相关资源
    最近更新 更多