Фильтровать список пар (кортежей), в которых кортеж не содержит значений из другого списка - PullRequest
2 голосов
/ 27 апреля 2019

У меня есть список кортежей:

my_list = [(1,2),(2,3),(3,4),(4,5),(5,6),(7,8)]

и список значений, которые я хочу исключить, которые имеют формат:

reference_list = [(2,20),(3,46),(4,918)] 

Значение, которое я хочу исключить:первый из пары.(Значение 20, 46, 918 не имеет значения)

Так что я хотел бы вернуть список кортежей, которые не содержат ни одного из 2,3, 4 значений.

Ожидаемый результат:

[(5,6),(7,8)] 

(поскольку все остальные содержат одно или несколько значений 2, 3 или 4)

Что я пробовал:

[p for p in my_list if p[0] not in [v[0] for v in reference_list] and p[1] not in [v[0] for v in reference_list]]

Я проверяю, нет ли первого или второго значения пары в списке v [0] списка ссылок.

Это работает, но я ищу болеекраткий / питонический способ, если есть.Идеально расширяемый (без простого добавления условий, таких как p [2] нет в списке и p [3] нет в списке и.

Ответы [ 3 ]

3 голосов
/ 27 апреля 2019

Флэт лучше, чем вложенный

blacklist = {p[0] for p in blacklist_of_tuples}
[p for p in my_list if p[0] not in blacklist and p[1] not in blacklist]

Это не решает обобщенный случай, но вы можете сделать это с тире any:

[p for p in my_list if not any(el in blacklist for el in p)]
2 голосов
/ 27 апреля 2019

Использование списка-списка с any():

[x for x in lst1 if not any(y[0] in x for y in lst2)]

Код :

lst1 = [(1,2),(2,3),(3,4),(4,5),(5,6),(7,8)]
lst2 = [(2,20),(3,46),(4,918)] 

set_lst2 = set(lst2)
print([x for x in lst1 if not any(y[0] in x for y in set_lst2)])
# [(5, 6), (7, 8)]
1 голос
/ 27 апреля 2019

Из соображений производительности для больших списков вы должны создать набор, содержащий первые элементы второго списка:

list_a = [(1,2),(2,3),(3,4),(4,5),(5,6),(7,8)]
list_b = [(2,20),(3,46),(4,918)]

set_b = {t[0] for t in list_b}

result = [t for t in list_a if not set_b.intersection(t)]

Как правило, метод intersection немного быстрее, чем any:

%timeit [t for t in list_a if not set_b.intersection(t)]
2.7 µs ± 377 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%timeit [t for t in list_a if not any(el in set_b for el in t)]
4.97 µs ± 479 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...