将string拆分为单词和标点符号

我试图将string拆分成单词和标点符号,将标点符号添加到拆分生成的列表中。

例如:

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

我真正想要的列表是:

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

所以,我希望string以空格分隔标点符号。

我试图parsingstring,然后运行拆分:

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

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

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

这或多或less是这样做的:

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

诀窍是,不要去考虑拆分string的位置,而是要考虑在记号中包含什么。

注意事项:

  • 下划线(_)被认为是一个内字的字符。 replace\ w,如果你不想要的话。
  • 这不适用于string中的(单个)引号。
  • 在正则expression式的右半部分添加任何想要使用的标点符号。
  • 在re中没有明确提到的任何内容都被无声地抛弃了。

这是一个Unicode感知版本:

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

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

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

在Perl风格的正则expression式语法中, \b匹配一个字边界。 这应该派上用场做一个基于正则expression式的拆分。

编辑:我已经被跳转告知,“空匹配”不能在Python的re模块的分割函数中工作。 我将把这里留下来作为任何人被这个“function”困住的信息。

这是我的入口。

我怀疑这样做是否有效,或者如果它抓住所有的情况(注意“!!!”分组在一起,这可能会或可能不是一件好事)。

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

一个显而易见的优化是,如果你要逐行地完成这个工作,先手动编译正则expression式(使用re.compile)。

这里是你的实现的一个小的更新。 如果你想做更详细的事情,我build议你看看dorfierbuild议的NLTK。

这可能只是快一点,因为''.join()被用来代替+ =,这是已知的更快 。

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

我想你可以在NLTK中find所有你可以想象的帮助,尤其是在你使用python的时候。 本教程中对此问题进行了全面的讨论。

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

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

这里.*?\S.*? 是一种匹配任何不是空格的模式,如果它是一个标点符号, $被添加到匹配string中的最后一个标记。

请注意以下事项 – 这将组成多个符号组成的标点符号:

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

当然,你可以find并拆分这样的组:

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

尝试这个:

 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 

你有没有尝试过使用正则expression式?

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


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

[0]

“”

[1]

“”

所以如果你想添加“,”你可以在每次迭代之后使用数组。