检查列表中是否包含另一个列表中所有类型的元素

4
我有两个Python列表:componentssignature。我想检查在signature中列出的类型是否与组件列表中的至少一个元素相匹配。
这里,签名匹配组件列表,因为在components中有一个字符串和一个浮点数:
signature = [float, str]
components = [1.0, [], 'hello', 1]

这里,签名组件不匹配,因为没有列表类型。
signature = [float, list]
components = ['apple', 1.0]

我该如何在Python 3中表达这个条件?
2个回答

7
您可以使用嵌套的生成器表达式和 all()any() 的组合来实现此功能。在此,我使用 isinstance() 来检查您的 signature 列表中的每个 type 是否与 components 列表中的对象匹配。使用此方法,您的自定义函数将如下所示:
def check_match(signature, components):
    return all(any(isinstance(c, s) for c in components) for s in signature)

示例运行:

# Example 1: Condition is matched - returns `True`
>>> signature = [str, int]
>>> components = [1, 'hello', []]
>>> check_match(signature, components)
True

# Example 2: Condition is not matched - returns `False`
>>> signature = [float, list]
>>> components = ['apple', 1.0]
>>> check_match(signature, components)
False

解释: 上述嵌套生成器表达式由两部分组成。第一部分是:

all(...`any()` call... for s in signature)

在这里,我正在遍历signature列表,以获取其中每个元素s。只有当所有...any() call...逻辑返回True时,all()才会返回True。否则它将返回False
第二个是...any() call...生成器表达式,如下所示:
any(isinstance(c, s) for c in components)

这里,对于components列表中的每个元素c,我正在检查是否从外部生成式匹配类型s。如果有任何匹配的类型,any(..)会返回True。如果没有任何c符合条件,则any(...)将返回False


1
太棒了 - 非常感谢。我知道这与any()和all()有关,但在实践中我没怎么用过它们。 - Ashley

1
另一种方法是计算组件中使用的类型集与您在签名中拥有的类型之间的差异。
unique_signatures = set(signature)
components_type = set(map(type, components))

types_not_used = unique_signatures.difference(components_type)

if len(types_not_used)==0:
    print('All types used')
else:
    print('Types not used:', types_not_used)

我相信这种解决方案有两个主要优点:
  1. 如果您的组件列表很长且存在许多重复类型,则更加高效,因为您可以减少比较次数
  2. 您希望匹配类时有多精确?子类是否应该通过测试?例如,isinstance(1, object)True:您认为这种行为是可取的吗?

使用@Moinuddin的(非常好的)答案提供的函数,您将获得以下结果:

check_match([object], [1, 2.0, 'hello'])
Out[20]: True

当我的回答检查 object 与 ['int', 'float', 'str'] 不匹配时。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接