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

时间:2008-12-14 23:30:34

标签: python string split

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

例如:

>>> c = "help, me"
>>> print c.split()
['help,', 'me']

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

['help', ',', 'me']

所以,我希望字符串在空白处拆分,并从单词中分割出标点符号。

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

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

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

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

12 个答案:

答案 0 :(得分:76)

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

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

诀窍是,不要考虑拆分字符串的位置,而是考虑包含在令牌中的内容。

注意事项:

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

答案 1 :(得分:30)

这是一个支持Unicode的版本:

re.findall(r"\w+|[^\w\s]", text, re.UNICODE)

第一个替代方案捕获单词字符序列(由unicode定义,因此“简历”不会变成['r', 'sum']);第二个捕获单个非单词字符,忽略空格。

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

答案 2 :(得分:5)

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

编辑:我已经被hop告知,“空匹配”在Python的re模块的split函数中不起作用。我会把这个留在这里作为其他任何被这个“特征”难倒的人的信息。

答案 3 :(得分:3)

这是我的参赛作品。

我怀疑这在效率方面会有多好,或者如果能抓住所有情况(请注意“!!!”组合在一起;这可能是也可能不是一件好事。)< / p>

>>> 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', ':']
>>>

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

答案 4 :(得分:1)

这是对您的实施的一个小更新。如果你想做更详细的事情,我建议你查看le dorfier建议的NLTK。

这可能只会快一点,因为''。join()代替+ =,即known to be faster

import string

d = "Hello, I'm a string!"

result = []
word = ''

for char in d:
    if char not in string.whitespace:
        if char not in string.ascii_letters + "'":
            if word:
                    result.append(word)
            result.append(char)
            word = ''
        else:
            word = ''.join([word,char])

    else:
        if word:
            result.append(word)
            word = ''
print result
['Hello', ',', "I'm", 'a', 'string', '!']

答案 5 :(得分:0)

我认为您可以在NLTK中找到所有可以想象的帮助,特别是因为您使用的是python。在教程中对此问题进行了很好的全面讨论。

答案 6 :(得分:0)

我想出了一种使用不需要硬编码的\W+来标记所有单词和\b模式的方法:

>>> import re
>>> sentence = 'Hello, world!'
>>> tokens = [t.strip() for t in re.findall(r'\b.*?\S.*?(?:\b|$)', sentence)]
['Hello', ',', 'world', '!']

此处.*?\S.*?是匹配任何非空格的模式,如果它是标点符号,则添加$以匹配字符串中的最后一个标记。

请注意以下内容 - 这将对包含多个符号的标点符号进行分组:

>>> print [t.strip() for t in re.findall(r'\b.*?\S.*?(?:\b|$)', '"Oh no", she said')]
['Oh', 'no', '",', 'she', 'said']

当然,您可以使用以下命令查找和拆分此类组:

>>> for token in [t.strip() for t in re.findall(r'\b.*?\S.*?(?:\b|$)', '"You can", she said')]:
...     print re.findall(r'(?:\w+|\W)', token)

['You']
['can']
['"', ',']
['she']
['said']

答案 7 :(得分:0)

试试这个:

string_big = "One of Python's coolest features is the string format operator  This operator is unique to strings"
my_list =[]
x = len(string_big)
poistion_ofspace = 0
while poistion_ofspace < x:
    for i in range(poistion_ofspace,x):
        if string_big[i] == ' ':
            break
        else:
            continue
    print string_big[poistion_ofspace:(i+1)]
    my_list.append(string_big[poistion_ofspace:(i+1)])
    poistion_ofspace = i+1

print my_list

答案 8 :(得分:0)

如果您要使用英语(或其他一些通用语言)工作,则可以使用NLTK(还有很多其他工具可以使用,例如FreeLing)。

import nltk
sentence = "help, me"
nltk.word_tokenize(sentence)

答案 9 :(得分:0)

这对我有用

import re

i = 'Sandra went to the hallway.!!'
l = re.split('(\W+?)', i)
print(l)

empty = ['', ' ']
l = [el for el in l if el not in empty]
print(l)

Output:
['Sandra', ' ', 'went', ' ', 'to', ' ', 'the', ' ', 'hallway', '.', '', '!', '', '!', '']
['Sandra', 'went', 'to', 'the', 'hallway', '.', '!', '!']

答案 10 :(得分:-1)

您是否尝试过使用正则表达式?

http://docs.python.org/library/re.html#re-syntax


顺便说一下。为什么你需要第二个“,”?你会知道每个文字写完后,即

[0]

“”

[1]

“”

因此,如果您想添加“,”,您可以在每次迭代后使用数组时执行此操作。

答案 11 :(得分:-1)

如果您不允许导入任何东西,请使用此功能!

word = "Hello,there"
word = word.replace("," , " ," )
word = word.replace("." , " .")
return word.split()