Итерация по списку и использование remove () не дает желаемого результата - PullRequest
0 голосов
/ 14 июля 2020

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

Моя цель состоит в том, чтобы функция читала текстовый файл, содержащий слова (может быть заглавными буквами), удалить пробелы, разделить элементы на отдельные строки, преобразовать все первые заглавные символы в нижний регистр, удалить все отдельные символы (например, «a», «b», «c», et c.) и добавить полученные слова в список. Все слова должны быть отдельным пунктом в списке для дальнейшей обработки.

Входной файл: текстовый файл ('sample.txt') содержит следующие данные - «яблоко b банан c вишня»

Желаемый результат: ['яблоко', 'банан', 'вишня']

В своей первоначальной попытке я попытался перебрать список слов, чтобы проверить, равна ли их длина 1. В таком случае слово должно было быть удалено из списка, а остальные слова оставались в списке. Это привело к следующему нежелательному результату: [None, None, None]

filename = ‘sample.txt’

with open(filename) as input_file:
    word_list = input_file.read().strip().split(' ')
    word_list = [word.lower() for word in word_list]
    word_list = [word_list.remove(word) for word in word_list if len(word) == 1]

print(word_list)

Произведен нежелательный результат = [None, None, None]

Моя следующая попытка была вместо этого перебирать список слов, чтобы проверить, была ли их длина больше 1. Если да, слово должно было быть добавлено в список (оставляя отдельные символы позади). Желаемый результат был достигнут с помощью этого метода.

filename = ‘sample.txt’

with open(filename) as input_file:
    word_list = input_file.read().strip().split(' ')
    word_list = [word.lower() for word in word_list]
    word_list = [word for word in word_list if len(word) > 1]

print(word_list)

Произведено желаемое Результат = ['яблоко', 'банан', 'вишня']

Мои вопросы:

  1. Почему исходный код не дал желаемого результата, когда он казался наиболее логичным и эффективным?
  2. Каков наилучший «питонический» способ достижения желаемого результата?

Ответы [ 4 ]

1 голос
/ 14 июля 2020

Причина, по которой вы получили результат:

  1. Вы удаляете элементы из списка, когда просматриваете его в цикле
  2. Вы пытаетесь использовать вывод list.remove (который просто изменяет список и возвращает None)

Ваше последнее понимание списка (word_list = [word_list.remove(word) for word in word_list if len(word) == 1]) по существу эквивалентно этому:

new_word_list = []
for word in word_list:
    if len(word) == 1:
        new_word_list.append(word_list.remove(word))
word_list = new_word_list

И как вы l oop через это происходит:

# word_list == ['a', 'apple', 'b', 'banana', 'c', 'cherry']
# new_word_list == []

word = word_list[0]  # word == 'a'

new_word_list.append(word_list.remove(word))

# word_list == ['apple', 'b', 'banana', 'c', 'cherry']
# new_word_list == [None]

word = word_list[1]  # word == 'b'

new_word_list.append(word_list.remove(word))

# word_list == ['apple', 'banana', 'c', 'cherry']
# new_word_list == [None, None]

word = word_list[2]  # word == 'c'

new_word_list.append(word_list.remove(word))

# word_list == ['apple', 'banana', 'cherry']
# new_word_list == [None, None, None]

word_list = new_word_list

# word_list == [None, None, None]

Лучший способ сделать это (на мой взгляд) Pythoni c:

with open('sample.txt') as input_file:
    file_content = input_file.read()

word_list = []
for word in file_content.strip().split(' '):
    if len(word) == 1:
        continue
    word_list.append(word.lower())

print(word_list)
0 голосов
/ 14 июля 2020
  1. Почему исходный код не дал желаемого результата, когда он казался наиболее логичным и наиболее эффективным?

Рекомендуется никогда не изменять list, перебирая его. Это связано с тем, что он перебирает представление исходного списка, и это представление будет отличаться от исходного.

Какой лучший "питонический" способ достичь желаемого результата?

Ваша вторая попытка. Но я бы использовал лучшее соглашение об именах, и ваши представления можно было бы объединить, поскольку вы делаете их строчными буквами только в первом:

word_list = input_file.read().strip().split(' ')
filtered_word_list = [word.lower() for word in word_list if len(word) > 1]
0 голосов
/ 14 июля 2020

Вторая попытка самая pythoni c. Первого все еще можно достичь с помощью следующего:

filename = 'sample.txt'

with open(filename) as input_file:
    word_list = input_file.read().strip().split(' ')

word_list = [word.lower() for word in word_list]

for word in word_list:
    if len(word) == 1:
        word_list.remove(word)

print(word_list)
0 голосов
/ 14 июля 2020

В вашем первом подходе вы сохраняете результат word_list.remove(word) в списке, который имеет значение None. Метод bcz list.remove () ничего не возвращает, кроме выполнения действия с заданным списком.

Ваш второй подход - это pythoni c способ достижения вашей цели.

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