我想我想做的是一项相当常见的任务,但我在网上找不到任何参考资料。我有带标点符号的文本,我想要一个单词列表。
"Hey, you - what are you doing here!?"
应该是
['hey', 'you', 'what', 'are', 'you', 'doing', 'here']
但Python的str.split()只对一个参数有效,所以在用空格拆分后,所有单词都带有标点符号。有什么想法吗?
我想我想做的是一项相当常见的任务,但我在网上找不到任何参考资料。我有带标点符号的文本,我想要一个单词列表。
"Hey, you - what are you doing here!?"
应该是
['hey', 'you', 'what', 'are', 'you', 'doing', 'here']
但Python的str.split()只对一个参数有效,所以在用空格拆分后,所有单词都带有标点符号。有什么想法吗?
当前回答
专业提示:使用string.translate进行Python最快的字符串操作。
一些证据。。。
首先,缓慢的方式(抱歉pprzemek):
>>> import timeit
>>> S = 'Hey, you - what are you doing here!?'
>>> def my_split(s, seps):
... res = [s]
... for sep in seps:
... s, res = res, []
... for seq in s:
... res += seq.split(sep)
... return res
...
>>> timeit.Timer('my_split(S, punctuation)', 'from __main__ import S,my_split; from string import punctuation').timeit()
54.65477919578552
接下来,我们使用re.findall()(如建议的答案所示)。更快:
>>> timeit.Timer('findall(r"\w+", S)', 'from __main__ import S; from re import findall').timeit()
4.194725036621094
最后,我们使用translate:
>>> from string import translate,maketrans,punctuation
>>> T = maketrans(punctuation, ' '*len(punctuation))
>>> timeit.Timer('translate(S, T).split()', 'from __main__ import S,T,translate').timeit()
1.2835021018981934
说明:
string.translate是用C实现的,与Python中的许多字符串操作函数不同,string.ttranslate不会生成新字符串。所以它的速度和字符串替换一样快。
不过,这有点尴尬,因为它需要一个翻译表来实现这一魔术。您可以使用maketrans()方便函数创建转换表。这里的目标是将所有不需要的字符转换为空格。一换一的替代品。同样,不会产生新数据。所以这很快!
接下来,我们使用旧的split()。默认情况下,split()将对所有空白字符进行操作,将它们分组以进行拆分。结果将是您想要的单词列表。而且这种方法几乎比re.findall()快4倍!
其他回答
我正在重新熟悉Python,需要同样的东西。findall解决方案可能更好,但我想到了这个:
tokens = [x.strip() for x in data.split(',')]
使用maketrans和translate,您可以轻松、整洁地完成
import string
specials = ',.!?:;"()<>[]#$=-/'
trans = string.maketrans(specials, ' '*len(specials))
body = body.translate(trans)
words = body.strip().split()
正则表达式对正的情况:
import re
DATA = "Hey, you - what are you doing here!?"
print re.findall(r"[\w']+", DATA)
# Prints ['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']
使用panda的series.str.split方法可以获得相同的结果,而不是使用re-module函数re.split。
首先,使用上述字符串创建一个系列,然后将该方法应用于该系列。
thestring=pd.Series(“嘿,你-你在这里干什么!?”)thestring.str.split(pat=',|-')
参数pat接受分隔符并将拆分字符串作为数组返回。这里,使用|(或运算符)传递两个分隔符。输出如下:
[嘿,你,你在这里干什么!?]
我喜欢re,但这是我没有它的解决方案:
from itertools import groupby
sep = ' ,-!?'
s = "Hey, you - what are you doing here!?"
print [''.join(g) for k, g in groupby(s, sep.__contains__) if not k]
sep__contains__是“in”运算符使用的方法。基本上与
lambda ch: ch in sep
但在这里更方便。
groupby获取字符串和函数。它使用该函数将字符串分成多个组:每当函数值发生变化时,就会生成一个新的组。因此,sep__contains__正是我们需要的。
groupby返回一个对序列,其中对[0]是我们函数的结果,对[1]是一个组。使用“if not k”,我们筛选出带有分隔符的组(因为sep.__contains__的结果在分隔符上为True)。好了,就这些了-现在我们有一个组序列,每个组都是一个单词(组实际上是一个可迭代的,所以我们使用join将其转换为字符串)。
这个解决方案非常通用,因为它使用一个函数来分隔字符串(您可以根据需要的任何条件进行拆分)。此外,它不创建中间字符串/列表(您可以删除join,因为每个组都是一个迭代器,所以表达式将变得懒惰)