#python #python-3.x #list #sorting
#python #python-3.x #Список #сортировка
Вопрос:
У меня есть функция create_profanity_output()
(см. Ниже весь код), в которой каждая ненормативная лексика из файла расшифровки добавляется в список, за которым следуют временные метки и символы цензуры. Я хочу сохранить порядок, в котором элементы отображаются в расшифровке.
Но моя проблема в том, что порядок добавленных элементов не такой, как в расшифровке. Я думал, что append()
это добавит элемент всегда в конец списка (который будет соответствовать исходному порядку). Но похоже, что ругательства отсортированы в алфавитном порядке, хотя я не использовал эту sorted()
функцию.
Если быть более точным, текущий (нежелательный) вывод выглядит следующим образом:
# Current output in wrong order.
[['fart', '00:00:03,950', '00:00:06,840', '****'],
['damn', '00:00:03,950', '00:00:06,840', '****'],
['damn', '00:00:03,950', '00:00:06,840', '****'],
['erotic', '00:00:03,950', '00:00:06,840', '****'],
Но внешний вид элементов в файле 1) fart, 2) эротический, 3) проклятый, 4) проклятый, поэтому желаемый результат будет:
# Target output in correct order.
[['fart', '00:00:03,950', '00:00:06,840', '****'],
['erotic', '00:00:03,950', '00:00:06,840', '****'],
['damn', '00:00:03,950', '00:00:06,840', '****'],
['damn', '00:00:03,950', '00:00:06,840', '****'],
Эта проблема также возникает, когда в расшифровке больше ненормативной лексики. Как только они имеют одинаковую временную метку, они сортируются в алфавитном порядке вместо сохранения их первоначального порядка. Я попытался отсортировать список следующим образом:
sorted_output = sorted(profanity_output, reversed=True)
,
sorted_output = sorted(profanity_output, reversed=False)
,
sorted_output = sorted(profanity_output, key=lambda x: x[0])
,
и тому подобное, но без достижения моей цели.
Я знаю, что это тривиальный вопрос. Но порядок ругательств не должен быть алфавитным. Кто-нибудь знает, почему append()
так действует и как я могу решить эту проблему?
Весь код:
def create_profanity_output():
"""Create a list 'profanity_output' which shall contain each profanity,
its timestamp and the default censor characters ('****')."""
profanity_output = []
# Define censor characters that occur in the transcript.
censor_chars = "****"
# Create lists with transcript data.
line_numbers = []
timestamps = []
text_lines = []
# Get lines from the transcript that contain strings according to the
# following pattern: 'line number', 'timestamp', 'text line', '' (empty
# string).
lines = transcript.splitlines()
# Iterate over 'lines' to get each single element from it. Divide the
# range object by 4 because of the 'lines' object's structure: (0: line
# number, 1: timestamp, 2: text line, 3: empty string).
for x in range(int(len(lines) / 4)):
# Increment iterable by 4. The * sign allows to always move 4
# elements further to the next "profanity cycle".
x = x * 4
# Add relevant elements to lists.
line_numbers.append(lines[x])
timestamps.append(lines[x 1])
text_lines.append(lines[x 2])
# Iterate over transcript data and create a zip object.
for line_number, timestamp, text_line in zip(line_numbers, timestamps,
text_lines):
# Create a list with timestamp strings: '00:00:03,950', '-->',
# '00:00:06,840'.
time_splits = timestamp.split()
for swearword in wordlist.splitlines():
# Iterate over tokenized text lines.
for word in text_line.split():
if word == swearword:
profanity_output.append([word, f"{time_splits[0]}",
f"{time_splits[2]}",
censor_chars])
return profanity_output
# Call function.
profanity_output = create_profanity_output()
print(profanity_output)
Комментарии:
1. Можем ли мы увидеть ваш ввод?
2. Однако вам обязательно следует изменить способ поиска по ругательствам. Было бы лучше разобрать
wordlist
один раз как aset
и посмотреть, еслиword in swearword_set
.3. Просто переключите вложенные циклы for
for swearword...
иfor word...
. Внешний цикл управляет порядком.4. @MichaelButscher: Ура, теперь это работает! Большое вам спасибо!
Ответ №1:
Как упоминал Майкл Бутчер в комментариях, ваша проблема в том, что for loops
они расположены в неправильном порядке. В настоящее время порядок вашего списка ругательств определяет порядок добавления слов в том же text_line
самом. Переключение порядка циклов даст вам правильный порядок.
Однако лучшим решением является предварительный анализ ваших ругательств. Это по-прежнему сохранит порядок слов, упорядоченный в text_line
, но также ускорит поиск (и это просто лучшая практика, даже если вам не нужна скорость).
swearwords = set(wordlist.splitlines())
for word in text_line.split():
if word in swearwords:
...
Комментарии:
1. Спасибо за ваш ответ и ваше объяснение, а также за дополнительный совет по разбору ругательств. Я скорректирую это в своем коде.
Ответ №2:
Ваш вывод для одной и той же строки фактически упорядочен по порядку ругательств в wordlist
. Итак, вы сначала выбираете ненормативную лексику, а затем просматриваете строку, чтобы увидеть, существует ли она. На самом деле вам нужно сначала выполнить итерацию по строке. Вы также можете использовать __contains__
функцию списка, чтобы увидеть, действительно ли ваше слово является ругательством.
Вот так:
swearwords = wordlist.splitlines()
# Iterate over tokenized text lines.
for word in text_line.split():
if word in swearwords:
profanity_output.append([word, f"{time_splits[0]}",
f"{time_splits[2]}",
censor_chars])