Как удалить одинаковый элемент для нескольких списков python?
Есть несколько списков в Python, пример:
list_1 = ['a', 'None', 'b', 'None', 'None', 'c', 'None', 'd']
list_2 = ['a', 'None', 'b', 'c', 'None', 'd', 'None',]
list_3 = ['a', 'None', 'b', 'None', 'None', 'c', 'None', 'd', 'e', 'f']
Не обязательно, чтобы размер у этих списков был одинаковый. Подскажите, пожалуйста, как удалить из нескольких списков значение "None" (да, в нашем списке None это строка) на одинаковых индексах?
Например, в итоге должен остаться лишь такие значения в списках:
list_1 = ['a', 'b', 'None', 'c', 'd']
list_2 = ['a', 'b', 'c', 'd']
list_3 = ['a', 'b', 'None', 'c', 'd', 'e', 'f']
В коде эти списки хранятся в словаре. Пример:
some_dict = {
'key1' = list_1,
'key2' = list_2,
'key3' = list_3,
}
Пока что не могу сообразить в алгоритм, который тут проще и легче всего применить. Огромная просьба учитывать наличие самого словаря. Буду очень признателен за подсказку!
Ответы (4 шт):
Как вариант — можно пробежаться циклом for сразу по всем трем спискам.
Для этого воспользуемся функцией zip(), а также создадим переменную индекса, с которым в данный момент работаем:
for index, (a, b, c) in enumerate(zip(*some_dict.values())):
. . .
Далее, внутри цикла проверим условие, то что текущий элемент 1, 2 и 3 списка равен 'None' и, если это так, то удалим текущий индекс из всех трех списков (при условии, что индекс не выходит за границы списка):
for index, (a, b, c) in enumerate(zip(*some_dict.values())):
if a == b == c == 'None':
for list_ in (list_1, list_2, list_3):
if index < len(list_):
del list_[index]
Если вывести все три списка после этих манипуляций, то на выходе получим результат:
['a', 'b', 'None', 'c', 'd']
['a', 'b', 'c', 'd']
['a', 'b', 'None', 'c', 'd', 'e', 'f']
Полный код:
some_dict = {
'key1': ['a', 'None', 'b', 'None', 'None', 'c', 'None', 'd'],
'key2': ['a', 'None', 'b', 'c', 'None', 'd', 'None',],
'key3': ['a', 'None', 'b', 'None', 'None', 'c', 'None', 'd', 'e', 'f'],
}
for index, (a, b, c) in enumerate(zip(*some_dict.values())):
if a == b == c == 'None':
for list_ in some_dict.values():
if index < len(list_):
del list_[index]
print(*some_dict.values(), sep='\n')
Для расширения ассортимента
В коде сделано допущение, что все элементы не приводятся к False
from itertools import zip_longest
result = {}
for v in zip_longest(*some_dict.values(), fillvalue=False):
if not all(map(lambda x: x == 'None', v)):
for k, y in zip(some_dict.keys(), v):
if y:
result.setdefault(k, []).append(y)
print(*result.values(), sep='\n')
еще вариант для ассортимента:
from itertools import compress, zip_longest
filt = [not a==b==c=='None' for a,b,c in zip_longest(*some_dict.values())]
some_dict = {k:list(compress(v, filt)) for k,v in some_dict.items()}
>>> some_dict
'''
{'key1': ['a', 'b', 'None', 'c', 'd'],
'key2': ['a', 'b', 'c', 'd'],
'key3': ['a', 'b', 'None', 'c', 'd', 'e', 'f']}
Ещё один вариант с zip_longest. В качестве fillvalue используется уникальный объект, что гарантирует корректную работу с любыми данными.
import itertools
def clean(lists):
keys, sources = zip(*lists.items())
targets = [[] for _ in sources]
blank = object()
for v in itertools.zip_longest(*sources, fillvalue=blank):
if any(map(lambda x: x != 'None', v)):
for i, t in zip(v, targets):
if i is not blank:
t.append(i)
return dict(zip(keys, targets))
lists = {
'key1': ['a', 'None', 'b', 'None', 'None', 'c', 'None', 'd'],
'key2': ['a', 'None', 'b', 'c', 'None', 'd', 'None'],
'key3': ['a', 'None', 'b', 'None', 'None', 'c', 'None', 'd', 'e', 'f']
}
result = clean(lists)
{'key1': ['a', 'b', 'None', 'c', 'd'], 'key2': ['a', 'b', 'c', 'd'], 'key3': ['a', 'b', 'None', 'c', 'd', 'e', 'f']}