удалить второй элемент, который начинается с той же подстроки - PullRequest
3 голосов
/ 15 мая 2019

У меня есть список l = ['abcdef', 'abcd', 'ghijklm', 'ghi', 'xyz', 'pqrs']
Я хочу удалить элементы, начинающиеся с одной и той же подстроки, если они существуют (в данном случае 'abcd' и 'ghi').
NB: в моей ситуации я знаю, что «повторяющиеся» элементы, если они существуют, могут быть только «abcd» или «ghi».
Чтобы удалить их, я использовал это:

>>> l.remove('abcd') if ('abcdef' in l and 'abcd' in l) else l
>>> l.remove('ghi') if ('ghijklm' in l and 'ghi' in l) else l
>>> l
>>> ['abcdef', 'ghijklm', 'xyz', 'pqrs']

Есть ли более эффективный (или более автоматизированный) способ сделать это?

Ответы [ 6 ]

2 голосов
/ 15 мая 2019

Вы можете сделать это за линейное время и O (n * м²) памяти (где m - длина ваших элементов):

prefixes = {}
for word in l:
    for x in range(len(word) - 1):
        prefixes[word[:x]] = True

result = [word for word in l if word not in prefixes]

Перебирать каждое слово и создавать словарь из первого символакаждого слова, затем первые два символа, затем три, вплоть до всех символов слова, кроме последнего.Затем снова выполните итерацию по списку, и если слово появляется в этом словаре, это более короткое подмножество другого слова в списке

1 голос
/ 15 мая 2019

@ Путь Эндрю Аллена

l = ['abcdef', 'abcd', 'ghijklm', 'ghi', 'xyz', 'pqrs']
i=0
l = sorted(l)
while True:
 try:
  if l[i] in l[i+1]:
   l.remove(l[i])
   continue
  i += 1
 except:
  break
print(l)
#['abcdef', 'ghijklm', 'pqrs', 'xyz']
1 голос
/ 15 мая 2019

Следующий код выполняет то, что вы описали.

your_list = ['abcdef', 'abcd', 'ghijklm', 'ghi', 'xyz', 'pqrs']
print("Original list: %s" % your_list)
helper_list = []
for element in your_list:
    for element2 in your_list:
        if element.startswith(element2) and element != element2:
            print("%s starts with %s" % (element, element2))
            print("Remove: %s" % element)
            your_list.remove(element)
print("Removed list: %s" % your_list)

Вывод:

Original list: ['abcdef', 'abcd', 'ghijklm', 'ghi', 'xyz', 'pqrs']
abcdef starts with abcd
Remove: abcdef
ghijklm starts with ghi
Remove: ghijklm
Removed list: ['abcd', 'ghi', 'xyz', 'pqrs']

С другой стороны, я думаю, что есть более простое решение, и вы можете решить его с помощью спискапонимание, если хотите.

1 голос
/ 15 мая 2019

Попробуйте это будет работать

l =['abcdef', 'abcd', 'ghijklm', 'ghi', 'xyz', 'pqrs']
for i in l:
    for j in l:
        if len(i)>len(j) and j in i:
            l.remove(j)
1 голос
/ 15 мая 2019
l = ['abcdef', 'abcd', 'ghijklm', 'ghi', 'xyz', 'pqrs']

for a in l[:]:
    for b in l[:]:
        if a.startswith(b) and a != b:
            l.remove(b)
print(l)

выход

['abcdef', 'ghijklm', 'xyz', 'pqrs']
0 голосов
/ 15 мая 2019

Вы можете использовать

l = ['abcdef', 'abcd', 'ghijklm', 'ghi', 'xyz', 'pqrs']
if "abcdef" in l:  # only 1 check for containment instead of 2
    l = [x for x in l if x != "abcd"]  # to remove _all_ abcd
    # or
    l = l.remove("abcd")               # if you know there is only one abcd in it

Это может быть немного быстрее (если у вас гораздо больше элементов, чем вы показываете), потому что вам нужно только один раз проверить «abcdef», а затем один раз развернуть первый / весь список для замены.

>>> l.remove('abcd') if ('abcdef' in l and 'abcd' in l) else l

дважды проверяет l на полный размер, чтобы проверить содержание (если не повезло), а затем все еще нужно что-то удалить из него


ПРЕДУПРЕЖДЕНИЕ:
Если это НЕ доказано, измерено узкое место или критично для безопасности и т. Д. Я бы не стал делать это , если У меня нет измерений, которые предполагают, что это самая большая экономия времени / оптимизация всех код в целом ... со списками до нескольких десятков / сотен (чувство живота - ваши данные не поддерживают какой-либо анализ), ожидаемый выигрыш от него незначителен.

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