将字符串拆分为单词和标点符号

Dav*_*d A 57 python string split

我正在尝试将字符串拆分为单词和标点符号,将标点符号添加到拆分生成的列表中.

例如:

>>> c = "help, me"
>>> print c.split()
['help,', 'me']
Run Code Online (Sandbox Code Playgroud)

我真正希望列表看起来像是:

['help', ',', 'me']
Run Code Online (Sandbox Code Playgroud)

所以,我希望字符串在空格中分割,并且从单词中分割出标点符号.

我试图先解析字符串,然后运行拆分:

>>> for character in c:
...     if character in ".,;!?":
...             outputCharacter = " %s" % character
...     else:
...             outputCharacter = character
...     separatedPunctuation += outputCharacter
>>> print separatedPunctuation
help , me
>>> print separatedPunctuation.split()
['help', ',', 'me']
Run Code Online (Sandbox Code Playgroud)

这会产生我想要的结果,但在大文件上却很慢.

有没有办法更有效地做到这一点?

小智 82

这或多或少是这样做的方式:

>>> import re
>>> re.findall(r"[\w']+|[.,!?;]", "Hello, I'm a string!")
['Hello', ',', "I'm", 'a', 'string', '!']
Run Code Online (Sandbox Code Playgroud)

诀窍是,不要考虑在哪里拆分字符串,而是要包含在令牌中的内容.

注意事项:

  • 下划线(_)被认为是一个内部字符.如果您不想要,请替换\ w.
  • 这不适用于字符串中的(单个)引号.
  • 在正则表达式的右半部分放置要使用的任何其他标点符号.
  • 在re中没有明确提到的任何内容都会被默默地删除.

  • 如果你想分割任何标点符号,包括```,请尝试`re.findall(r"[\ w] + | [^\s\w]","你好,我是一个字符串!")`.结果是'['Hello',',','I',''','m','a','string','!']`注意,数字包含在单词匹配中. (3认同)

LaC*_*LaC 32

这是一个支持Unicode的版本:

re.findall(r"\w+|[^\w\s]", text, re.UNICODE)
Run Code Online (Sandbox Code Playgroud)

第一种方法是捕获单词字符序列(由unicode定义,因此"简历"不会变成['r', 'sum']); 第二个捕获单个非单词字符,忽略空格.

请注意,与最佳答案不同,这会将单引号视为单独的标点符号(例如"我是" - > ['I', "'", 'm']).这似乎是NLP的标准,所以我认为它是一个功能.

  • 由于`\ w + | [^\w\s]`构造比接受的答案更通用但在python 3中afaik,因此re.UNICODE不应该是upvoted (2认同)

Fer*_*ino 7

如果您打算使用英语(或其他一些常用语言)工作,则可以使用NLTK(有许多其他工具可以执行此操作,例如FreeLing)。

import nltk
sentence = "help, me"
nltk.word_tokenize(sentence)
Run Code Online (Sandbox Code Playgroud)


小智 6

这是我的条目。

我怀疑这在效率方面的效果如何,或者它是否可以捕获所有情况(注意“!!!”组合在一起;这可能是也可能不是一件好事)。

>>> import re
>>> import string
>>> s = "Helo, my name is Joe! and i live!!! in a button; factory:"
>>> l = [item for item in map(string.strip, re.split("(\W+)", s)) if len(item) > 0]
>>> l
['Helo', ',', 'my', 'name', 'is', 'Joe', '!', 'and', 'i', 'live', '!!!', 'in', 'a', 'button', ';', 'factory', ':']
>>>
Run Code Online (Sandbox Code Playgroud)

如果您要逐行执行此操作,则一个明显的优化是事先编译正则表达式(使用 re.compile)。


Sva*_*nte 5

在perl样式的正则表达式语法中,\b匹配单词边界.这对于进行基于正则表达式的拆分应该会派上用场.

编辑:我已经被hop告知,"空匹配"在Python的re模块的split函数中不起作用.我会把这个留在这里作为其他任何被这个"功能"困扰的人的信息.