Python 基于任意字段查找字典列表的交集

Python 基于任意字段查找字典列表的交集,python,list,dictionary,intersection,Python,List,Dictionary,Intersection,假设我有一个字典列表l1和l2。每个都包含相同格式的词典。我想根据字典的某个字段找到l1和l2的交集 例如,让 l1 = [{"key":1, "key2":2}, {"key":1, "key2":0}], l2 = [{"key":0, "key2":2}]. 我想根据“键2”将它们相交。 所以,l1.intersect(l2)=2 如果我没弄错的话,我可以这样做,它的复杂性是O(len(l1)+len(l2)) d = defaultdict(bool) for e in l2:

假设我有一个字典列表
l1
l2
。每个都包含相同格式的词典。我想根据字典的某个字段找到
l1
l2
的交集

例如,让

l1 = [{"key":1, "key2":2}, {"key":1, "key2":0}],
l2 = [{"key":0, "key2":2}]. 
我想根据“键2”将它们相交。 所以,
l1.intersect(l2)=2

如果我没弄错的话,我可以这样做,它的复杂性是O(len(l1)+len(l2))

d = defaultdict(bool)
for e in l2:
    d[e['key2']] = True
intersection=set()
for e in l1:
    if d[e['key2']]:
        intersection.add(e['key2])

我想知道的是,是否存在更好的解决方案,或者我的解决方案是否已经是最优的。

您可以使用集合理解来简化此过程。比如说,

l1 = [{"key":1, "key2":2}, {"key":3, "key2":4}, {"key":5, "key2":6}, {"key":7, "key2":8}]
l2 = [{"key":0, "key2":2}, {"key":1, "key2":3}, {"key":2, "key2":4}]

key = "key2"
values = {d[key] for d in l1} & {d[key] for d in l2}
print(values)
输出

{2, 4}

通过在函数中执行集合理解,可以使代码更具可读性,尽管函数调用会使代码在微观上更慢

def key_set(seq, key):
    return {d[key] for d in seq}

values = key_set(l1, key) & key_set(l2, key)
这种技术可以推广到处理任意数量的列表

all_lists = (l1, l2)
key = "key2"
values = set.intersection(*({d[key] for d in seq} for seq in all_lists))

您可以通过使用集合理解使其紧凑。比如说,

l1 = [{"key":1, "key2":2}, {"key":3, "key2":4}, {"key":5, "key2":6}, {"key":7, "key2":8}]
l2 = [{"key":0, "key2":2}, {"key":1, "key2":3}, {"key":2, "key2":4}]

key = "key2"
values = {d[key] for d in l1} & {d[key] for d in l2}
print(values)
输出

{2, 4}

通过在函数中执行集合理解,可以使代码更具可读性,尽管函数调用会使代码在微观上更慢

def key_set(seq, key):
    return {d[key] for d in seq}

values = key_set(l1, key) & key_set(l2, key)
这种技术可以推广到处理任意数量的列表

all_lists = (l1, l2)
key = "key2"
values = set.intersection(*({d[key] for d in seq} for seq in all_lists))

你的字典名字没有多大意义。字典是一组键:值对。因此,您将一个键命名为“key”,另一个键命名为“value”。这只是一个简化的示例。字典可以包含任意数量的字段。如果在第二个dict中将
“key”:1
您是正确的。我对它进行了相应的编辑。为什么要使用
defaultdict(bool)
而不是set呢?你的字典名称没有太多意义。字典是一组键:值对。因此,您将一个键命名为“key”,另一个键命名为“value”。这只是一个简化的示例。字典可以包含任意数量的字段。如果在第二个dict中将
“key”:1
您是正确的。我已经对它进行了相应的编辑。为什么要使用
defaultdict(bool)
而不是set?但在您的示例中,它不需要更多的时间吗?因此,我们首先从l1获取值,然后从l2获取值。这已经是len(l1)+len(l2)。之后,我们进行集合交集。@SpiderRico True,这使得时间复杂度O(len(l1)+len(l2))+O(min(len(l1),len(l2)),仍然是O(len(l1)+len(l2))但是,集合的理解速度非常快,更重要的是,交叉运算是以C速度完成的,这比使用
if
测试的Python循环要快得多。但是在您的示例中,它不需要花费更多的时间吗?所以我们先从l1获取值,然后从l2获取值。这已经是len(l1)+len(l2)。然后我们做集合交集。@SpiderRico为True,这使得时间复杂度O(len(l1)+len(l2))+O(min(len(l1),len(l2)),仍然是O(len(l1)+len(l2))但是,集合理解非常快,更重要的是,交叉操作是以C速度完成的,这比使用
if
测试的Python循环要快得多。