Нахождение пересечения списка словарей на основе произвольного поля - PullRequest
0 голосов
/ 30 августа 2018

Скажите, у меня есть список словарей l1 и l2. Каждый содержит словари одного формата. Я хотел бы найти пересечение l1 и l2 на основе некоторого поля словаря.

Например, пусть

l1 = [{"key":1, "key2":2}, {"key":1, "key2":0}],
l2 = [{"key":0, "key2":2}]. 

Я бы хотел пересечь их по ключу "key2". Итак, 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])

Что мне интересно, так это если существует лучшее решение или мое решение уже оптимально.

1 Ответ

0 голосов
/ 30 августа 2018

Вы можете сделать это компактно, используя набор пониманий. Например,

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))
...