Токенизация не английского текста в Python
У меня есть персидский текстовый файл, который имеет несколько строк, как это:
ذوب 6 خوی 7 بزاق ،آبدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف
Я хочу создать список слов из этой строки. Для меня границы слова - это числа, такие как 6, 7 и т. Д. В приведенной выше строке, а также ،
персонаж. поэтому список должен быть:
[ 'ذوب','خوی','بزاق','آبدهان','یم','زهاب','آبرو','حیثیت' ,'شرف']
Я хочу сделать это в Python 3.3. Каков наилучший способ сделать это, я действительно ценю любую помощь в этом.
РЕДАКТИРОВАТЬ:
Я получил несколько ответов, но когда я использовал их для другого теста, они не работали. Контрольный пример таков:
منهدم کردن : 1 خراب کردن، ویران کردن، تخریب کردن 2 نابود کردن، از بین بردن
и я ожидаю получить список токенов, как это:
['منهدم کردن','خراب کردن', 'ویران کردن', 'تخریب کردن','نابود کردن', 'از بین بردن']
2 ответа
С помощью regex
пакет:
>>> import regex
>>> text = 'ذوب 6 خوی 7 بزاق ،آبدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف'
>>> regex.findall(r'\p{L}+', text.replace('\u200c', ''))
['ذوب', 'خوی', 'بزاق', 'آبدهان', 'یم', 'زهاب', 'آبرو', 'حیثیت', 'شرف']
- Текст содержит нулевую ширину без соединения (U+200C). удалил персонажа используя
str.replace
, \p{L}
или же\p{Letter}
соответствует любому виду букв на любом языке.
См. Regex Tutorial - Символы и свойства Unicode.
ОБНОВИТЬ
Чтобы также включить U+200C, используйте [\p{Cf}\p{L}]+
вместо (\p{Cf}
или же \p{Format}
соответствует невидимому символу форматирования):
>>> regex.findall(r'[\p{Cf}\p{L}]+', text)
['ذوب', 'خوی', 'بزاق', 'آب\u200cدهان', 'یم', 'زهاب', 'آبرو', 'حیثیت', 'شرف']
Выглядит иначе, чем вы хотите, но они равны:
>>> got = regex.findall(r'[\p{Cf}\p{L}]+', text)
>>> want = [ 'ذوب','خوی','بزاق','آبدهان','یم','زهاب','آبرو','حیثیت' ,'شرف']
>>> print(want)
['ذوب', 'خوی', 'بزاق', 'آب\u200cدهان', 'یم', 'زهاب', 'آبرو', 'حیثیت', 'شرف']
>>> got == want
>>> got[:3]
['ذوب', 'خوی', 'بزاق']
>>> got[4:]
['یم', 'زهاب', 'آبرو', 'حیثیت', 'شرف']
UPDATE2
Некоторые слова в редактируемом вопросе содержат пробел.
>>> ' ' in 'منهدم کردن'
True
я добавил \s
в следующем коде также сопоставьте пробелы, затем уберите начальные, конечные пробелы из сопоставленных строк, а затем отфильтруйте пустые строки.
>>> text = 'منهدم کردن : 1 خراب کردن، ویران کردن، تخریب کردن 2 نابود کردن، از بین بردن'
>>> want = ['منهدم کردن','خراب کردن', 'ویران کردن', 'تخریب کردن','نابود کردن', 'از بین بردن']
>>> [x for x in map(str.strip, regex.findall(r'[\p{Cf}\p{L}\s]+', text)) if x] == want
True
Использование re.split
разбить на пробел (\s
), цифры (\d
) и ،
персонаж.
# python 3
import re
INPUT = 'ذوب 6 خوی 7 بزاق ،آبدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف'
EXPECTED = [ 'ذوب','خوی','بزاق','آبدهان','یم','زهاب','آبرو','حیثیت' ,'شرف']
OUTPUT = re.split('[\s\d،]+', INPUT)
assert OUTPUT == EXPECTED
print('\n'.join(OUTPUT))
Обратите внимание \u200c
вы видите в выходном массиве непечатный символ, который фактически содержится в исходной строке. Python избегает его, поскольку он показывает представление массива и содержащих его строк, а не печатает строку для отображения. Вот разница:
INPUT = 'ذوب 6 خوی 7 بزاق ،آبدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف'
print(INPUT)
ذوب 6 خوی 7 بزاق ،آبدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف
print(repr(INPUT)) # notice the \u200c below
'ذوب 6 خوی 7 بزاق ،آب\u200cدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف'
print(['in', 'an', 'array', INPUT]) # the \u200c is also shown when printing an array
['in', 'an', 'array', 'ذوب 6 خوی 7 بزاق ،آب\u200cدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف']
Это похоже на то, как Python обрабатывает newline
персонажи:
>>> 'new\nline'
'new\nline'
>>> print 'new\nline'
new
line
Редактировать:
Вот регулярное выражение для вашего обновленного примера, в котором используется стратегия findall от Falsetru, но используется встроенный re
модуль:
OUTPUT = [s.strip() for s in re.findall(r'(?:[^\W\d_]|[\s])+', INPUT) if s.strip()]
Шаблон (?:[^\W\d_]|[\s])+
немного странно, так как модуль re в Python не имеет эквивалента регулярным выражениям \p{L}
поэтому вместо этого мы используем предложенное здесь решение /questions/6757982/sootvetstvuet-tolko-bukve-unicode-v-python/6757992#6757992
[^\W\d_] - (not ((not alphanumeric) or digits or underscore))
Итак, в итоге, сопоставьте один или несколько символов (+
) которые либо (|
): Юникод буквы [^\W\d_
или пробел \s
,
Метод falsetru, вероятно, более читабелен, но требует сторонней библиотеки.