Как сделать Python split () на языках (таких как китайский), которые не используют пробелы в качестве разделителя слов?

Я хочу разбить предложение на список слов.

Для английского и европейского языков это просто, просто используйте split ()

>>> "This is a sentence.".split()
['This', 'is', 'a', 'sentence.']

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

>>> u"这是一个句子".split()
[u'\u8fd9\u662f\u4e00\u4e2a\u53e5\u5b50']

Очевидно, что это не работает.

Как мне разбить такое предложение на список слов?

ОБНОВИТЬ:

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

Так откуда же возникает двусмысленность? Как вы можете видеть в выводе моей консоли Python, Python без проблем сообщает, что мое примерное предложение состоит из 5 символов:

这 - u8fd9
是 - u662f
一 - u4e00
个 - u4e2a
句 - u53e5
子 - u5b50

Поэтому, очевидно, у Python нет проблем с указанием границ слова / символа. Мне просто нужны эти слова / символы в списке.

 NullUserException26 сент. 2010 г., 18:57
@ Продолжение "Границы слова в китайском языке кажутся мне очень определенными". Смотрите мой комментарий к ответу Марка Байерса
 Porculus26 сент. 2010 г., 15:16
Перевод 字 как «слова» является распространенным, но вводящим в заблуждение.字 означает символ, а не слово. Слово в английском смысле это 詞.
 Continuation26 сент. 2010 г., 15:05
Похоже, что путаница происходит от значения «слово» против «характер». Я просто никогда не думал о «句子» как об одном отдельном слове. Каждый китайский символ представляет собой «a», что переводится как «слово». «句子» явно имеет два «字», и поэтому я никогда не думал об этом как об одном слове.
 JUST MY correct OPINION26 сент. 2010 г., 14:23
Краткий ответ: нет.
 Jim Brissom26 сент. 2010 г., 14:23
Ну, что китайцы используют в качестве разделителя слов?
 sth26 сент. 2010 г., 14:57
@ Продолжение: разве это не одно слово? «Границы символов» не являются проблемой, так как просто каждый символ Unicode - это один китайский символ. Сложнее всего узнать, какие китайские иероглифы принадлежат одному слову.

Ответы на вопрос(8)

Решение Вопроса

list( '...' ) (в Py3; этоu'...' для Py2) будетнев общем смысле, дать вамперсонажи строки Юникода; скорее это скорее всего приведет к серии 16-битных кодовых точек. это верно для всех «узких» сборок CPython, на которые сегодня приходится подавляющее большинство установок Python.

когда в 1990-х годах впервые был предложен юникод, было высказано предположение, что 16 бит будет более чем достаточно для покрытия всех потребностей универсального кодирования текста, поскольку он позволяет перейти от 128 кодовых точек (7 бит) и 256 кодовых точек (8 бит) до колоссальных 65'536 кодов. однако вскоре стало очевидно, что это было желаемое за действительное; Сегодня в Unicode версии 5.2 определено около 100 000 кодовых точек, и еще тысячи ожидают включения. чтобы это стало возможным, юникод должен был перейти с 16 на (концептуально) 32 бита (хотя он не в полной мере использует 32-битное адресное пространство).

Для обеспечения совместимости с программным обеспечением, основанным на предположении, что Юникод по-прежнему составляет 16 бит, были разработаны так называемые суррогатные пары, где две 16-битовые кодовые точки из специально обозначенных блоков используются для выражения кодовых точек за пределами 65'536, то есть за пределами того, что Unicode называет «базовую многоязычную плоскость», или BMP, и которую в шутку называют «астральными» плоскостями этого кодирования, потому что их относительная неуловимость и постоянная головная боль они предлагают людям, работающим в области обработки и кодирования текста.

теперь, когда узкий CPython работает с суррогатными парами довольно прозрачно в некоторых случаях, он все равно не сможет делать правильные вещи в других случаях, при этом расщепление строк является одним из этих более проблемных случаев. в узкой сборке питона,list( 'abc大def' ) (или жеlist( 'abc\u5927\U00027C3Cdef' ) когда написано с escape-символами) приведет к['a', 'b', 'c', '大', '\ud85f', '\udc3c', 'd', 'e', 'f'], с'\ud85f', '\udc3c' будучи суррогатной парой. кстати,'\ud85f\udc3c' это то, что стандарт JSON ожидает от вас, чтобы представитьU-27C3C, любая из этих кодовых точек сама по себе бесполезна; У правильно сформированной строки Unicode могут быть только пары суррогатов.

так что вы хотите разделить строку на символы на самом деле:

from re import compile as _Re

_unicode_chr_splitter = _Re( '(?s)((?:[\ud800-\udbff][\udc00-\udfff])|.)' ).split

def split_unicode_chrs( text ):
  return [ chr for chr in _unicode_chr_splitter( text ) if chr ]

который правильно возвращает['a', 'b', 'c', '大', '', 'd', 'e', 'f'] (примечание: вы, вероятно, можете переписать регулярное выражение, так что фильтрация пустых строк становится ненужной).

если все, что вы хотите сделать, это разделить текст на китайские иероглифы, то на этом этапе вы бы почти закончили. не уверен, какова концепция «слова» в ОП, но для меня 这 是 一个 句子 может быть в равной степени разделена на 这 |是 |一 |个 |句子, а также 这 是 |一个 |句子, в зависимости от вашей точки зрения. однако все, что выходит за рамки понятия (возможно, составленных) символов и классов символов (символы против пробелов, букв и т. д.), выходит далеко за рамки того, что встроено в юникод и python; вам понадобится немного обработки естественного языка, чтобы сделать это. позвольте мне отметить, что пока ваш пример'yes the United Nations can!'.split() успешно демонстрирует, что метод split делает что-то полезное для большого количества данных, он неправильно разбирает английский текст на слова: он не может распознатьUnited Nations как одно слово, в то время как оно ложно предполагаетcan! это слово, которое это явно не так. этот метод дает как ложные срабатывания, так и ложные отрицания. в зависимости от ваших данных и того, что вы намерены выполнить, это может или не может быть тем, что вы хотите.

 hugo14 авг. 2019 г., 10:23
Упор на реализацию вопроса OP поднимает две совершенно разные проблемы (кодовые точки Юникода и понятие слова на китайском языке) и их решение отдельно, что почти никто здесь не делал.
 Stefan Sullivan12 окт. 2016 г., 03:24
Организация Объединенных Наций - это 2 слова, даже если это собственно существительное

где у вас обычно есть разные классы символов в начале и конце слова, но есть целые научные статьи на эту тему для китайского языка. У меня есть регулярное выражение для разделения слов на японском языке, если вам интересно:http://hg.hatta-wiki.org/hatta-dev/file/cd21122e2c63/hatta/search.py#l19

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

Задача, которую вы описываете, является частью поля, называемогоОбработка естественного языка (НЛП). Уже была проделана большая работа по разделению китайских слов на границах слов. Я бы посоветовал вам использовать одно из этих существующих решений, а не пытаться свернуть свое собственное.

Китайский нлпкитайский - группа Stanford NLP (обработка естественного языка)

Откуда возникает двусмысленность?

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

Если все, что вам нужно, это найти символы, то это очень просто и не требует библиотеки NLP. Просто декодируйте сообщение в строку Unicode (если это еще не сделано), а затем преобразуйте строку Unicode в список, используя вызов встроенной функции.list, Это даст вам список символов в строке. Для вашего конкретного примера:

>>> list(u"这是一个句子")
 NullUserException26 сент. 2010 г., 19:04
Таким образом, каждый из этих символов Юникода является Chinese для китайского языка, что не то же самое, что «слово» (词), но также не эквивалентно западной букве или слогу.
 Jim Brissom26 сент. 2010 г., 14:26
В самом деле. Я мог бы добавитьalias-i.com/lingpipe/demos/tutorial/chineseTokens/read-me.html
 NullUserException26 сент. 2010 г., 19:02
Подавляющее большинство китайских иероглифов имеют индивидуальный смысл сами по себе. В примере: «这 是 一个 句子» каждый из этих символов что-то означает - «这 = this», «是 = is», «一 = one», «个 = a», «句 = предложение». Сложная часть - это составные символы, которые означают одну «вещь» (например, «句子» = предложение). Также иногда составные символы имеют значение, совершенно отличное от отдельных символов.

Лучший инструмент токенизатора для китайцев - это pynlpir.

import pynlpir
pynlpir.open()
mystring = "你汉语说的很好!"
tokenized_string = pynlpir.segment(mystring, pos_tagging=False)

>>> tokenized_string
['你', '汉语', '说', '的', '很', '好', '!']

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

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

    regex = r"[\u4e00-\ufaff]|[0-9]+|[a-zA-Z]+\'*[a-z]*"
    matches = re.findall(regex, str, re.UNICODE)
    return matches

как китайский, имеют очень плавное определение слова. Например. Одно значениеma это "лошадь". Одно значениеshang "выше" или "сверху". Составом является «mashang», что буквально означает «верхом», но в переносном смысле означает «немедленно». Вам нужен очень хороший словарь с соединениями, а поиск словаря требует подхода с наибольшим соответствием. Компаунды распространены на немецком языке (известный пример - что-то вроде «жены директора Дунайской пароходной компании», выражаемой одним словом), тюркские языки, финский и мадьярский - в этих языках очень длинные слова, многие из которых не встречаются в словарь и нужно разбираться, чтобы понять их.

Ваша проблема связана с лингвистикой, а не с Python.

 Continuation26 сент. 2010 г., 14:50
Я предполагаю, что у нас просто есть различное использование термина "слово" при применении его к китайскому языку. Для меня "ma shang" ("马上") - это просто 2 слова / символа. 1st является первым, 上 является вторым.
 John Machin26 сент. 2010 г., 15:10
Для меня слово - это строка из одного или нескольких символов, которая имеет особое значение. Обратите внимание, что некоторые символы не имеют собственного значения и имеют смысл только в сочетании с другим персонажем. Список персонажей не очень полезен.

То, что мне нужно, можно сделать, просто используя list ():

>>> list(u"这是一个句子")
[u'\u8fd9', u'\u662f', u'\u4e00', u'\u4e2a', u'\u53e5', u'\u5b50']

Спасибо за ваш вклад.

 flow26 сент. 2010 г., 21:35
я бы сказал, что оставь ОП, что он считает полезным. и завтрак - это, действительно, «сломать» «пост», съесть снова после того, как перестал делать это на некоторое время. не полезно?
 John Machin26 сент. 2010 г., 15:13
-1 То, что тебе нужно, не очень полезно. Это все равно что пытаться извлечь значение слова «завтрак» из двух отдельных понятий «перерыв» и «быстрый».
 John Machin26 сент. 2010 г., 23:11
@flow: "завтрак"было (не «есть»), чтобы «разорвать» «быстрый» ... связь такая же ненадежная, как «девять драконов» -> «Коулун»
 mlvljr27 мая 2011 г., 23:47
Обилие одних прекрасных китайских символов и прочих здесь заставляет меня завидовать тем, кто действительно может их прочитать;)
 Jesse17 июл. 2017 г., 03:00
Это ответ только для китайского предложения. Как насчет гибридного английского / китайского в одном предложении? Ответ на гибридный сплитгибридно-сплит.
 flow27 сент. 2010 г., 01:31
Коулун 九龍 в буквальном смысле означает девять драконов, по крайней мере, для миллиардов людей, которые не знают лучше. Как вкратце говорится в «Википедии»: «相傳 九龍 地名 由來 由來. что касается завтрака,thefreedictionary.com/breakfast предлагает: «Среднеанглийский завтрак: брекен, сломаться; увидеть брейк + фаст, быстрый (от древнескандинавского фаста до быстрого; см. прошлое в индоевропейских корнях») и, ну, «было», «есть», «будет», что угодно.

Ваш ответ на вопрос