Как индексировать, удалять и подсчитывать все экземпляры элемента в списке?

Я новичок в 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

С какими входными данными вы это тестируете? Первые несколько, которые я пробовал, работают нормально.

Patrick Haugh 28.01.2019 15:48

Просто небольшая проблема, но наличие print('Letter not found.') после вашего оператора return... эта строка никогда не будет выполнена.

TrebledJ 28.01.2019 16:16

@TrebuchetMS Хорошо, приятно знать, но почему? :-)

Tim Struppi 28.01.2019 17:07

@PatrickHaugh Для ввода я использую (тестирование): satz='Dies soll in eine Liste übertragen werden.' lst=[] lst.extend(satz)

Tim Struppi 28.01.2019 17:07

Предполагается ли, что эта функция изменяет переданный список? lst.remove(letter) удаляет все буквы из lst, поэтому, когда вы снова вызываете removing, в списке остается 0 таких букв.

Patrick Haugh 28.01.2019 17:11

@PatrickHaugh Да, предполагается изменить переданный список. Если я попытаюсь изменить клонированный список, я не смогу получить к нему доступ с помощью print()... Есть ли способ сделать это по-другому?

Tim Struppi 28.01.2019 17:13

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

Patrick Haugh 28.01.2019 17:16

да. Как правило, если вам нужно добавить несколько строк кода в комментарий, этот комментарий должен быть либо изменением вопроса, либо ответом.

Patrick Haugh 28.01.2019 17:23

@PatrickHaugh Вопрос был отредактирован. Пока спасибо за совет :-)

Tim Struppi 28.01.2019 17:33

Что касается вашего другой комментарий, то в характере инструкции return немедленно выйти из функции. В результате строка, следующая за оператором return (print('Letter not found')), никогда не будет выполнена.

TrebledJ 28.01.2019 17:54

@TrebuchetMS Понятно.

Tim Struppi 28.01.2019 18:01

Все строки в Python уже являются списками, и почему бы вместо этого просто не использовать re.sub()?

accdias 28.01.2019 22:10
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
12
63
3

Ответы 3

Ваш цикл не нужен, и он будет бесконечным. Попробуйте ниже

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

Ты прав. Я сделал цикл только для того, чтобы повторять это несколько раз. И еще раз спасибо.

Tim Struppi 28.01.2019 17:51

Не проще ли использовать re.sub как re.sub('a', '', 'abracadabra')?

accdias 28.01.2019 22:12

@accdias Это не соответствует требованию возврата списка удаленных индексов.

Patrick Haugh 28.01.2019 22:12

Ой! Я понимаю. Так что вместо него можно использовать re.finditer().

accdias 28.01.2019 22:20

Что-то вроде этого [i.span()[0] for i in re.finditer('a', 'abracadabra')] даст список индексов всех вхождений a в abracadabra.

accdias 28.01.2019 22:28

Всем спасибо за помощь, на мой вопрос ответили. Проблема была не в функции, а в том, что я несколько раз вызывал функцию без сохранения результата. Окончательный код выглядит так:

    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)

Patrick Haugh 28.01.2019 17:52
фейспалм Должен был заметить, что когда разрыва не было.
Tim Struppi 28.01.2019 18:05

Вот мое решение:

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])
>>> 

Интересный. Я не знал ни одного из этих операторов. Рассмотрю их. Спасибо

Tim Struppi 29.01.2019 10:51

Я рад помочь вам, и было бы здорово, если бы вы отметили один из ответов как действительный для решения проблемы. Это, безусловно, поможет другим пользователям с тем же вопросом.

accdias 30.01.2019 12:44

Другие вопросы по теме