如何在不使用空格作为单词分隔符的语言(如中文)上执行PythonSplit()? [英] How to do a Python split() on languages (like Chinese) that don't use whitespace as word separator?
问题描述
我要将一个句子拆分成单词列表。
对于英语和欧洲语言,这很容易,只需使用Split()
>>> "This is a sentence.".split()
['This', 'is', 'a', 'sentence.']
但我还需要处理中文等不使用空格作为单词分隔符的句子。
>>> u"这是一个句子".split()
[u'u8fd9u662fu4e00u4e2au53e5u5b50']
这显然行不通。
如何将这样的句子拆分成单词列表?
更新:
到目前为止,答案似乎表明这需要自然语言处理技术,而且中文的单词边界是模糊的。我不确定我明白为什么。在我看来,汉语中的单词界限似乎非常明确。每个中文单词/字符都有对应的Unicode,并在屏幕上显示为单独的单词/字符。
那么模棱两可是从哪里来的呢?正如您在我的Python控制台输出中看到的那样,Python毫不费力地告诉您我的示例句子由5个字符组成:
这 - u8fd9
是 - u662f
一 - u4e00
个 - u4e2a
句 - u53e5
子 - u5b50
因此,很明显,Python可以毫不费力地判断单词/字符的边界。我只需要列表中的那些单词/字符。
unicode
只需提醒一句:使用list( '...' )
(在推荐答案中是u'...'
)将不是,从一般意义上讲,它将为您提供unicode字符串的字符;相反,它很可能产生一系列16位代码点。对于所有"狭窄的"CPython版本来说都是如此,这占了当今绝大多数的Python安装。
为了保持与基于Unicode仍然是16位的假设而构建的软件的兼容性,设计了所谓的代理对,其中来自特定指定块的两个16位码点被用来表示超过65‘536的码点,也就是超出Unicode所称的’基本多语言平面‘或BMP的码点,它们被戏称为该编码的’星形‘平面,因为它们相对难以捉摸,给文本处理和编码领域的工作人员带来了持续的头痛。
现在,尽管Narrow CPython在某些情况下非常透明地处理代理项对,但在其他情况下它仍然不能做正确的事情,字符串拆分是比较麻烦的情况之一。在狭义的python构建中,list( 'abc大𧰼def' )
(或list( 'abcu5927U00027C3Cdef' )
如果用转义编写)将导致['a', 'b', 'c', '大', 'ud85f', 'udc3c', 'd', 'e', 'f']
,'ud85f', 'udc3c'
是代理项对。顺便说一句,'ud85fudc3c'
是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']
(注意:您可以重写正则表达式,这样就不需要过滤掉空字符串)。
如果您想要做的只是将文本拆分成中文字符,那么在这一点上您已经基本完成了。我不确定OP对‘单词’的概念是什么,但对我来说,这是一个句子可能分为这|是|一|个|句子和这是|一个|句子,这取决于您的观点。然而,任何超出字符和字符类(符号、空格和字母等)的概念的东西都远远超出了Unicode和Python的内置内容;您需要一些自然语言处理才能做到这一点。让我指出,虽然您的示例'yes the United Nations can!'.split()
确实成功地演示了Split方法对大量数据做了一些有用的事情,但它没有将英语文本正确地解析为单词:它无法将United Nations
识别为一个单词,而它错误地假设can!
是一个单词,而事实显然不是。这种方法既有假阳性,也有假阴性。这可能是您想要的,也可能不是您想要的,具体取决于您的数据和您要完成的任务。
这篇关于如何在不使用空格作为单词分隔符的语言(如中文)上执行PythonSplit()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!