Как я могу сравнить два списка списков в Python и найти совпадающие значения - PullRequest
0 голосов
/ 07 февраля 2020

Я пытаюсь сравнить два списка на основе порядкового номера каждого списка:

list1 = [
    ['1', ['a']],
    ['2', ['b', 'c', 'd']],
    ['3', ['e']],
    ['4', ['f', 'g']],
    ['5', ['h']]
]

list2 = [
    ['1', ['e']],
    ['2', ['f', 'c']],
    ['3', ['h', 'g', 'a', 'd']],
    ['4', ['b']],
    ['5', ['b']],
]

Я хотел бы сравнить каждую строку списка list1 со всеми строками в list2 и вернуть соответствующие значения. Например, в этом примере желаемый результат будет

1(list1) - 3(list2),
2-2,
2-3,
2-4,
2-5,
3-1, 
4-2, 
4-3

в общей сложности 8. А затем удалите похожие, такие как: 2-4 и 4-2, 1-3 и 3-1.

1 Ответ

0 голосов
/ 07 февраля 2020

Вы ищете набор пересечений из продукта ваших «меток», где каждая пара сама является набором (порядок не важно, если 2-4 и 4-2 считаются одинаковыми).

Пересечения наиболее эффективно тестируются с типом Python set , поэтому при построении этих словарей можно преобразовать их нужно настроить вперед.

Поэтому нам нужны уникальные метки и способ поиска связанного списка для каждой метки. Это работа для словарей, поэтому сначала преобразуйте свои списки в словари и получите объединение их ключей. Затем превратите каждую пару в набор, чтобы {'2', '4'} и {'4', '2'} выглядели одинаково, сохраняя результаты в другом наборе. Обратите внимание, что 2-2 становится 2 в этом сценарии, поскольку набор будет хранить '2' только один раз.

Тогда все, что нам нужно сделать, это проверить, есть ли пересечение между двумя списками, связанными с выбрал комбинацию клавиш и включил эту комбинацию, если есть:

from itertools import product

dict1 = {k: set(l) for k, l in list1}
dict2 = {k: set(l) for k, l in list2}
keys = dict1.keys() | dict2.keys()  # all unique keys in both

found = {
    frozenset((k1, k2))
    for k1, k2 in product(keys, repeat=2)
    if dict1.get(k1, set()) & dict2.get(k2, set())
}

Демо:

>>> from itertools import product
>>> dict1 = {k: set(l) for k, l in list1}
>>> dict2 = {k: set(l) for k, l in list2}
>>> keys = dict1.keys() | dict2.keys()  # all unique keys in both
>>> {
...     frozenset((k1, k2))
...     for k1, k2 in product(keys, repeat=2)
...     if dict1.get(k1, set()) & dict2.get(k2, set())
... }
{frozenset({'3', '4'}), frozenset({'2'}), frozenset({'3', '5'}), frozenset({'2', '5'}), frozenset({'2', '3'}), frozenset({'2', '4'}), frozenset({'1', '3'})}

Если у вас должны быть дублированные ссылки, вы можете постобработать результат:

for combo in found:
    try:
        a, b = combo
    except ValueError:  # doesn't contain 2 values, assume 1
        a, = b, = combo
    print(f'{a}-{b}')

Порядок будет зависеть от текущего случайного числа ha sh seed, поэтому вы можете использовать сортировку. Я получаю этот вывод:

3-4
2-2
3-5
2-5
2-3
2-4
1-3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...