Python разделяет двуязычный текстовый файл с табуляцией на два отдельных текстовых файла (список) с символами новой строки, разделяющими строки - PullRequest
0 голосов
/ 10 января 2019

У меня есть двуязычные корпуса (EN-JP) от tatoeba, и я хочу разделить их на два отдельных файла. Строки должны располагаться на одной строке соответственно.

Мне это нужно для обучения NMT в nmt-keras, и данные обучения должны храниться в отдельных файлах для каждого языка. Я попробовал несколько подходов, но так как я абсолютный новичок в области Python и кодирования в целом, я чувствую, что бегаю кругами.

Пока лучшее, что мне удалось, было следующее:

Исходный текст:

Go. 行け。
Go. 行きなさい。
Hi. やっほー。
Hi. こんにちは!

Код:

with open('jpns.txt', encoding="utf8") as f:
    columns = zip(*(l.split("\t") for l in f))

list1= list(columns)
print(list1)

[('Go.', 'Go.', 'Hi.', 'Hi.'), ('行け。\n', '行きなさい。\n', 'やっほー。\n', 'こんにちは!')]

Результат с моим кодом:

[('Go.', 'Go.', 'Hi.', 'Hi.'), ('行け。\n', '行きなさい。\n', 'やっほー。\n', 'こんにちは!')]

Английский и японский языки разделены должным образом (в кортеж?), Но я застрял в том, чтобы понять, как экспортировать только английский и как экспортировать только японский в output.en и output.jp соответственно.

Ожидаемый результат:

output.en

Go.
Go.
Hi.
Hi.

output.jp

行け。
行きなさい。
やっほー。
こんにちは!

Каждая выведенная строка должна содержать \ n после строки.

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

1 Ответ

0 голосов
/ 10 января 2019

Первое, что нужно знать, это то, что перебор файла сохраняет символы новой строки. Это означает, что в ваших двух столбцах первый не имеет новых строк, а второй имеет новые строки, уже добавленные к каждой строке (кроме, возможно, последней).

Поэтому запись второго столбца тривиальна, если вы уже распаковали генератор columns:

with open('output.jp', 'w') as f:
    f.writelines(list1[-1])

Но вам все равно придется добавлять новые строки в первый столбец (и, возможно, другие, если вы используете полный многоязычный язык). Один из способов - добавить новые строки ко всем столбцам, кроме последнего. Другой вариант - удалить столбцы из последнего столбца и обработать их все одинаково.

Вы можете достичь желаемого результата с помощью небольшого цикла и еще одного вызова zip:

langs = ('en', 'jp')
for index, (lang, data) in enumerate(zip(langs, columns)):
    with open('output.' + lang, 'w') as f:
        if index < len(langs) - 1:
            data = (line + '\n' for line in data)
        f.writelines(data)

Этот подход заменяет кортеж data генератором, который добавляет новые строки, если только мы не находимся в последнем столбце.

Есть несколько способов вставить новые строки между каждой строкой в ​​выходных файлах. Тот, который я показываю, использует ленивый генератор для добавления к каждой строке в отдельности. Это должно сохранить немного памяти. Если вам не нужна экономия памяти, вы можете вывести весь файл в виде одной строки:

joiner = '\n' if index < len(langs) - 1 else ''
f.write(joiner.join(data))

Вы даже можете написать цикл самостоятельно и print в файл:

for line in data:
    print(line, file=f, end='\n' if index < len(args) - 1 else '')

Добавление

Давайте также подробно рассмотрим строку columns = zip(*(l.split("\t") for l in f)), поскольку это очень распространенная идиома Python для транспонирования вложенных списков и ключ к получению желаемого результата.

Генераторное выражение l.split("\t") for l in f довольно просто: оно разбивает каждую строку в файле вокруг вкладок, давая вам два элемента, один на английском и один на японском. Добавление * перед генератором расширяет его так, что каждая строка из двух элементов становится отдельным аргументом для zip. zip затем повторно комбинирует соответствующие элементы каждой строки, так что вы получаете столбец английских элементов и столбец японских элементов, эффективно транспонируя вашу оригинальную «матрицу».

В результате columns является генератором столбцов. Вы можете преобразовать его в list, но это необходимо только для просмотра. Генератор будет работать нормально для кода, показанного выше.

...