Удалить последнее вхождение элемента, содержащего подстроку, из списка - PullRequest
0 голосов
/ 26 сентября 2019

Скажем, у меня есть, list1 = ['собака', 'кошка', 'кошка собака', 'собака убежала домой']

и sub_string = 'собака'

как я могу вернуть list2 = ['the dog', 'the cat', 'cat dog']

т.е. вернуть список с последним вхождением удаленной подстроки?

Ответы [ 5 ]

2 голосов
/ 26 сентября 2019

Никакая встроенная функция не поможет вам в этом, поскольку сканирование подстроки в list не поддерживается, и делать это в обратном порядке вдвойне сложно.Понимания списков тоже не принесут пользы, так как создание достаточного состояния для распознавания, когда вы нашли свою стрелку, потребует добавления побочных эффектов к пониманию списка, что делает его загадочным и нарушает назначение инструментов функционального программирования.Итак, вы застряли, выполняя цикл самостоятельно:

list2 = []
list1iter = reversed(list1)  # Make a reverse iterator over list1
for item in list1iter:
    if sub_string in item:   # Found item to remove, don't append it, we're done
        break
    list2.append(item)       # Haven't found it yet, keep item
list2.extend(list1iter)      # Pull all items after removed item
list2.reverse()              # Put result back in forward order

Попробуйте онлайн!

Альтернативным подходом будет сканирование по индексу, позволяющее вам del Это;это может быть лучшим решением, если вы хотите изменить list1 на месте, а не создавать новый list:

for i, item in enumerate(reversed(list1), 1):
    if sub_string in item:
        del list1[-i]
        break

Попробуйте онлайн!

Это решение можно адаптировать к созданию новой копии, просто изменив все ссылки на list1 на list2 и добавив list2 = list1[:] перед циклом.

В обоих случаях вы можете определить, был ли элементнайдено вообще, положив else: блок на for;если срабатывает блок else, вы не break, потому что sub_string нигде не было найдено.

1 голос
/ 26 сентября 2019

Одним из решений является обход входных данных в обратном порядке и поиск индекса в обратном списке.После этого используйте индекс, чтобы разделить входные данные list1.

idx = next(i for i, s in enumerate(reversed(list1), 1) if sub_string in s)
list2 = list1[:-idx]  # If in-place updates are intended, use `del list1[-idx:]` instead
1 голос
/ 26 сентября 2019
list1 = ['the dog', 'the cat','the dog me', 'cat dog']
sub_string = 'the dog'

for i in list1[::-1]:
    print(i)
    if sub_string in i:
        list1.remove(i)
        break

output ['the dog', 'the cat', 'the dog me', 'cat dog']

1 голос
/ 26 сентября 2019

Вы можете сделать это в два шага:

  1. Найти индекс последнего вхождения.
  2. Вернуть все элементы, которые не соответствуют этому индексу.

Пример:

needle = 'the dog'
haystack = ['the dog', 'the cat', 'cat dog', 'the dog ran home']

last = max(loc for loc, val in enumerate(haystack) if needle in val)
result = [e for i, e in enumerate(haystack) if i != last]

print(result)

Вывод

['the dog', 'the cat', 'cat dog']

Подробнее о поиске индекса последнего вхождения см. this .

1 голос
/ 26 сентября 2019

проблема заключается в следующем: удалить элемент с подстрокой в ​​качестве запроса

, поэтому, как я понял, он имеет два шага.

  1. Найтиэлемент с подстрокой.
  2. Удалите элемент.

для сопоставления с образцом, мы можем использовать модуль re (мы можем использовать in, как упоминалось в ответах ShadowRanger)

import re

pattern = re.compile('the dog') # target pattern 
my_list = ['the dog', 'the cat', 'cat dog', 'the dog ran home'] # our list
my_list = enumerate(my_list) # to get indexes corresponding to elemnts i.e. [(0, 'the dog'), (1, 'the cat'), (2, 'cat dog'), (3, 'the dog ran home')]
elems = list(filter(lambda x: pattern.search(x[1]), my_list) # match the elements in the second place and filter them out, remember filter in python 3.x returns an iterator
print(elems) # [(0, 'the dog'), (3, 'the dog ran home')]
del my_list[elems[-1][0]] # get the last element and take the index of it and delete it.

РЕДАКТИРОВАТЬ

Как и предполагал ShadowRunner, мы можем оптимизировать код с использованием понимания списка с помощью оператора if вместо filter function.

elems = [i for i, x in enumerate(my_list) if pattern.search(x)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...