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

Posted

技术标签:

【中文标题】将字符串拆分为单词和标点符号【英文标题】:Splitting a string into words and punctuation 【发布时间】:2010-09-26 21:34:58 【问题描述】:

我正在尝试,并将标点符号添加到拆分生成的列表中。

例如:

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

这会产生我想要的结果,但在大文件上速度非常慢。

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

【问题讨论】:

对于这个例子(不是一般情况)c.replace(' ','').partition(',') 【参考方案1】:

这或多或少是这样做的:

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

诀窍是,不要考虑在哪里拆分字符串,而是要在标记中包含什么。

注意事项:

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

【讨论】:

如果您想在任何标点符号处拆分,包括',请尝试re.findall(r"[\w]+|[^\s\w]", "Hello, I'm a string!")。结果是['Hello', ',', 'I', "'", 'm', 'a', 'string', '!'] 另请注意,单词匹配中包含数字。 对不起!你能解释一下这是如何工作的吗? @Curious:说实话,不,我不会。因为,我应该从哪里开始?你知道什么?哪个部分对您来说是个问题?你想达到什么目标? 没关系!我自己明白这一点!感谢您的回复:)【参考方案2】:

这是一个支持 Unicode 的版本:

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

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

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

【讨论】:

赞成,因为 \w+|[^\w\s] 构造比公认的答案更通用,但在 python 3 中 afaik re.UNICODE 不应该是必要的【参考方案3】:

如果你打算用英语(或其他一些常用语言)工作,你可以使用NLTK(还有很多其他工具可以做到这一点,例如FreeLing)。

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

【讨论】:

上面的(原始)代码对我来说失败,并出现关于需要 PUNKT 资源的错误。我建议在import nltk 之后添加nltk.download('punkt')【参考方案4】:

这是我的条目。

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

>>> 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)。

【讨论】:

加 1 用于分组标点符号。【参考方案5】:

这是对您的实施的一个小更新。如果您尝试做任何更详细的事情,我建议您查看 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', '!']

【讨论】:

我没有对此进行分析,但我想主要问题是单词的逐字符连接。我会改为使用索引和切片。 借助技巧,我可以将解决方案的执行时间缩短 50%。我使用 re.findall() 的解决方案仍然快两倍。 你需要在循环结束后调用if word: result.append(word),否则最后一个单词不在结果中。【参考方案6】:

这对我有用

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', '.', '!', '!']

【讨论】:

【参考方案7】:

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

【讨论】:

【参考方案8】:

我想出了一种方法来标记所有单词和 \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']

【讨论】:

【参考方案9】:

试试这个:

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

【讨论】:

【参考方案10】:

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

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


顺便说一句。为什么你需要第二个“,”?您会知道,在编写完每个文本后,即

[0]

","

[1]

","

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

【讨论】:

【参考方案11】:

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

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

【讨论】:

以上是关于将字符串拆分为单词和标点符号的主要内容,如果未能解决你的问题,请参考以下文章

使用动态编程将字符串拆分为有效单词的字符串

单词和排队标点字符的字符串拆分

PHP:将字符串拆分为数组 foreach char

Python在符号@后读取.text和拆分单词

RegEx Tokenizer:将文本拆分为单词、数字、标点和空格(不要删除任何内容)

将字符串拆分为第一个单词和其余文本?