【问题标题】:How to filter an array of objects on nested attribute using lambda and hasattr?如何使用 lambda 和 hasattr 过滤嵌套属性上的对象数组?
【发布时间】:2019-07-26 00:27:01
【问题描述】:

我有以下 Python 代码:

myArray = [{ "id": 1, "desc": "foo", "specs": { "width": 1, "height": 1}}, { "id": 2, "desc": "bar", "specs": { "width": 2, "height": 2, "color": "black"}}, { "id": 3, "desc": "foobar"}]
print len(myArray)

myArray_filtered = filter(lambda item : hasattr(item, "specs") and hasattr(item.specs, "color"), myArray)
print len(myArray_filtered)

我希望在第二次打印时得到长度 1,但它是 0。你能告诉我我的代码有什么问题吗?

【问题讨论】:

  • 如果你拆分你的条件,你会发现你的第一个过滤命令返回一个空列表——长度为 0,任何进一步的过滤都将返回长度 0。
  • @meowgoesthedog 我尝试使用myArray_filtered = filter(lambda item : 'specs' in item and 'color' in item.specs), myArray),但它不起作用。抱歉,这是我第一次使用 Python!
  • @hd1 是的,你是对的,我现在明白了……反正我不知道哪里出了问题。
  • @meowgoesthedog 你的答案比我的有优势,如果“颜色”的值为None 我需要使用另一个默认值

标签: python arrays object lambda hasattr


【解决方案1】:
myArray_filtered = [v for v in myArray if v.get('specs', {}).get('color')]
print(len(myArray_filtered))

仅使用列表推导稍微简单一些。

你可以添加到条件:

myArray_filtered = [v for v in myArray if v.get('specs', {}).get('color') and v.get('specs', {}).get('width') == 2]
print(len(myArray_filtered))

【讨论】:

  • 这种情况下如何添加width == 2等更多条件?
【解决方案2】:

鉴于您的嵌套结构,您可以使用带有一些默认值的dict.get

>>> myArray_filtered = list(filter(lambda d: d.get("specs", {}).get("color") is not None, myArray))
>>> len(myArray_filtered)
1
>>> myArray_filtered
[{'id': 2, 'desc': 'bar', 'specs': {'width': 2, 'height': 2, 'color': 'black'}}]

【讨论】:

  • @smartmouse 你只需要在 Python 3 中调用list(),但在这个阶段你真的不应该学习 Python 2
  • 我使用的是 Python 2.7.x,它可以在没有 list() 的情况下工作。谢谢。
  • 你知道如何添加更多条件吗?例如,如果我想检查width == 2 ?
  • @Chris_Rands 很好的解决方案,我有同样的问题,你已经解决了,但不是规范是一个对象,而是一个列表 [] 相同的例子如何与 [] 列表中的规范?
猜你喜欢
  • 2022-11-20
  • 2018-01-16
  • 1970-01-01
  • 1970-01-01
  • 2020-07-18
  • 1970-01-01
  • 2022-12-03
  • 2022-01-24
  • 1970-01-01
相关资源
最近更新 更多