#python
#python
Вопрос:
У меня есть длинный список вызываемых строк words
. Все строки имеют одинаковую длину, равную 5. Для любого i в {0, …,4} мы можем проверить, является ли i
‘-я буква строки также i-й буквой любой другой строки в списке. Мы называем букву в i
‘-й позиции уникальной, если это не так.
Я хотел бы удалить все строки из моего списка, для которых существует любая i
, для которой i
‘-я буква уникальна.
В качестве очень простого примера рассмотрим: words = ["apple", "amber", "bpple", "bmber", "appld"]
. Строка «appld» должна быть удалена, поскольку d
уникальна в 4-й позиции.
Есть ли аккуратный способ сделать это?
Комментарии:
1. Составьте список, элементы которого соответствуют каждому из исходных слов. Каждый элемент списка — это количество дубликатов соответствующей буквы. Когда вы закончите, удалите каждый элемент исходного списка, соответствующий списку, который содержит
1
.
Ответ №1:
Использование collections.Counter
и zip(*...)
идиома транспозиции:
from collections import Counter
# counts for every index
bypos = [*map(Counter, zip(*words))]
# disallow count 1 for any letter x in its respective position
words = [w for w in words if all(c[x]!=1 for x, c in zip(w, bypos))]
# ['apple', 'amber', 'bpple', 'bmber']
Обратите внимание, что лучше перестроить список за одну итерацию, чем повторно удалять элементы.
Некоторые документы по используемым здесь утилитам:
Ответ №2:
это можно сделать в O (NlogN), но пространство неэффективно
d={}
for j,w in enumerate(words):
for i,c in enumerate(w):
if (i,c) in d:
d[(i,c)].append(j)
else:
d[(i,c)]=[j]
for i in reversed(list(set([v[0] for v in d.values() if len(v)==1]))):
words.pop(i)
print(words)