Я новичок в Python, и я пытаюсь узнать что-то о списках. В этом случае моя цель — проиндексировать, подсчитать и удалить все экземпляры элемента в списке. Индексация, подсчет и удаление отлично работают по отдельности, но я изо всех сил пытаюсь объединить их и получить желаемые результаты. Что я делаю неправильно?
def removing(letter,lst):
'''This function should index and remove all entries of a letter within a list, returning the removed items' position within the original list. I then use len() function on the result-list to determine how many items have been indexed/deleted'''
result=[]
offset= -1
list_new = lst.copy()
while True:
try:
offset=list_new.index(letter, offset+1)
except ValueError:
return result
print('Letter not found.')
result.append(offset)
lst.remove(letter)
Теперь я ожидал, что даже без клонирования списка это сделает свое дело, и функция вернет позиции букв и удалит их, но когда я определяю lst и letter, запускаю функцию и затем говорю:
print(len(removing(letter,lst)))
Он всегда говорит 0. Почему это?
Обновлено: мне посоветовали вызвать функцию один раз и сохранить результат, но когда я делаю следующее, результат тот же:
c=1
print(lst)
while (c==1):
letter=input('What letter do you want to remove?\n')
if letter in lst:
var=removing(letter,lst)
print(var)
print(str(len(var))+' letters have been removed.')
print(lst)
else:
c-1
Просто небольшая проблема, но наличие print('Letter not found.') после вашего оператора return... эта строка никогда не будет выполнена.
@TrebuchetMS Хорошо, приятно знать, но почему? :-)
@PatrickHaugh Для ввода я использую (тестирование): satz='Dies soll in eine Liste übertragen werden.' lst=[] lst.extend(satz)
Предполагается ли, что эта функция изменяет переданный список? lst.remove(letter) удаляет все буквы из lst, поэтому, когда вы снова вызываете removing, в списке остается 0 таких букв.
@PatrickHaugh Да, предполагается изменить переданный список. Если я попытаюсь изменить клонированный список, я не смогу получить к нему доступ с помощью print()... Есть ли способ сделать это по-другому?
Итак, ваша проблема в том, что вы звоните дважды. Во второй раз нет букв для удаления. Вызовите функцию один раз и сохраните результат.
да. Как правило, если вам нужно добавить несколько строк кода в комментарий, этот комментарий должен быть либо изменением вопроса, либо ответом.
@PatrickHaugh Вопрос был отредактирован. Пока спасибо за совет :-)
Что касается вашего другой комментарий, то в характере инструкции return немедленно выйти из функции. В результате строка, следующая за оператором return (print('Letter not found')), никогда не будет выполнена.
@TrebuchetMS Понятно.
Все строки в Python уже являются списками, и почему бы вместо этого просто не использовать re.sub()?






Ваш цикл не нужен, и он будет бесконечным. Попробуйте ниже
lst = list('abracadabra')
letter = 'a'
var=removing(letter,lst)
print(var) # [0, 3, 5, 7, 10]
print(str(len(var))+' letters have been removed.') # 5 letters have been removed.
print(lst) # ['b', 'r', 'c', 'd', 'b', 'r']
Другой способ написать функцию немного более питоническим способом мог бы выглядеть примерно так:
def remove(lst, item):
new_list = []
indices = []
for i, x in enumerate(lst):
if x == item:
indices.append(i)
else:
new_list.append(x)
return new_list, indices
Ты прав. Я сделал цикл только для того, чтобы повторять это несколько раз. И еще раз спасибо.
Не проще ли использовать re.sub как re.sub('a', '', 'abracadabra')?
@accdias Это не соответствует требованию возврата списка удаленных индексов.
Ой! Я понимаю. Так что вместо него можно использовать re.finditer().
Что-то вроде этого [i.span()[0] for i in re.finditer('a', 'abracadabra')] даст список индексов всех вхождений a в abracadabra.
Всем спасибо за помощь, на мой вопрос ответили. Проблема была не в функции, а в том, что я несколько раз вызывал функцию без сохранения результата. Окончательный код выглядит так:
lst= list('Nach langem rumprobieren haben nette Menschen mir bei der Vollendung dieser kleinen Übungsaufgabe geholfen.')
def removing(letter,lst):
'This function should remove all entries of a letter within a list'
result=[]
offset= -1
list_new = lst.copy()
while True:
try:
offset=list_new.index(letter, offset+1)
except ValueError:
return result
result.append(offset)
lst.remove(letter)
c=1
print(lst)
while (c==1):
letter=input('What letter do you want to remove?\n')
if letter in lst:
var=removing(letter,lst)
print(var)
print(str(len(var))+' letters have been removed.')
print(lst)
else:
break
Обратите внимание, что ваш c-1 на самом деле не меняет значение c. Вместо этого попробуйте c -= 1. (Или просто break)
Вот мое решение:
import re
def removing(c, s):
'''This function removes all occurences of 'c' in 's' and return a list of the replaced indices'''
indices = [i.span()[0] for i in re.finditer(c, s)]
return s.replace(c, ''), indices
А вот пример использования:
>>> removing('a', 'abracadabra')
('brcdbr', [0, 3, 5, 7, 10])
>>>
>>> removing('a', 'aaaaa')
('', [0, 1, 2, 3, 4])
>>>
Интересный. Я не знал ни одного из этих операторов. Рассмотрю их. Спасибо
Я рад помочь вам, и было бы здорово, если бы вы отметили один из ответов как действительный для решения проблемы. Это, безусловно, поможет другим пользователям с тем же вопросом.
С какими входными данными вы это тестируете? Первые несколько, которые я пробовал, работают нормально.