在Python中使用元组查找列表中的元素

时间:2016-09-12 08:56:45

标签: python tuples

我有一些复杂的数据,想要找到 key 元组的特定元素。 target 元组与 key 略有不同,因为它具有 id 属性。所以我不能在目标 中使用 键。

那么在这种情况下实施智能搜索的最佳方法是什么?

targets = [
    {"id": 0, "X": (), "Y": (), "Z": () },
    {"id": 1, "X": (1,), "Y": (5,), "Z": ()},
    {"id": 2, "X": (1,), "Y": (5, 7), "Z": ()},
    {"id": 3, "X": (2,), "Y": (5, 7), "Z": (1,)},
    {"id": 4, "X": (1, 2), "Y": (5, 7), "Z": (1,)},
    {"id": 5, "X": (1, 2), "Y": (5, 7), "Z": (1,3)},
]

key = {"X": (1,), "Y": (5, 7), "Z": ()}

我想实现 find 方法来提取预期的插槽,如下所示。

In []: find(targets, key)
Out[]: {'id': 2, 'X': (1,), 'Y': (5, 7), 'Z': ()}

1 个答案:

答案 0 :(得分:2)

如果键值对必须完全匹配,您可以使用Dictionary view objects将键值对视为 sets 。您想要找到strict subset

def find(targets, key):
    for target in targets:
        if key.items() < target.items():
            return target

仅查找第一个匹配。

你可以把它变成一个单行:

next((target for target in targets if key.items() < target.items()), None)

如果您必须生成所有匹配,则可以在上述方法中将return替换为yield以将其转换为生成器,或者您可以使用列表解析:

[target for target in targets if key.items() < target.items()]

以上使用Python 3语法。在Python 2中,可以通过特殊的.viewkeys().viewvalues().viewitems()方法获得字典视图,因此将view添加到方法名称中:

def find(targets, key):
    # Python 2 version
    for target in targets:
        if key.viewitems() < target.viewitems():
            return target

演示(在Python 3上):

>>> targets = [
...     {"id": 0, "X": (), "Y": (), "Z": () },
...     {"id": 1, "X": (1,), "Y": (5,), "Z": ()},
...     {"id": 2, "X": (1,), "Y": (5, 7), "Z": ()},
...     {"id": 3, "X": (2,), "Y": (5, 7), "Z": (1,)},
...     {"id": 4, "X": (1, 2), "Y": (5, 7), "Z": (1,)},
...     {"id": 5, "X": (1, 2), "Y": (5, 7), "Z": (1,3)},
... ]
>>> key = {"X": (1,), "Y": (5, 7), "Z": ()}
>>> def find(targets, key):
...     for target in targets:
...         if key.items() < target.items():
...             return target
...
>>> find(targets, key)
{'Y': (5, 7), 'X': (1,), 'Z': (), 'id': 2}
>>> next((target for target in targets if key.items() < target.items()), None)
{'Y': (5, 7), 'X': (1,), 'Z': (), 'id': 2}
>>> [target for target in targets if key.items() < target.items()]
[{'Y': (5, 7), 'X': (1,), 'Z': (), 'id': 2}]