我想我想做的是一项相当常见的任务,但我在网上找不到任何参考资料。我有带标点符号的文本,我想要一个单词列表。

"Hey, you - what are you doing here!?"

应该是

['hey', 'you', 'what', 'are', 'you', 'doing', 'here']

但Python的str.split()只对一个参数有效,所以在用空格拆分后,所有单词都带有标点符号。有什么想法吗?


当前回答

另一种方式,不使用正则表达式

import string
punc = string.punctuation
thestring = "Hey, you - what are you doing here!?"
s = list(thestring)
''.join([o for o in s if not o in punc]).split()

其他回答

这么多的答案,但我找不到任何能有效解决问题标题所要求的问题的解决方案(而是在多个可能的分隔符上拆分,许多答案在任何非单词上拆分,这是不同的)。因此,这是标题中问题的答案,它依赖于Python的标准和高效的重新模块:

>>> import re  # Will be splitting on: , <space> - ! ? :
>>> filter(None, re.split("[, \-!?:]+", "Hey, you - what are you doing here!?"))
['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']

哪里:

[…]匹配其中列出的分隔符之一,正则表达式中的\-是为了防止将-作为字符范围指示符(如a-Z)进行特殊解释,+跳过一个或多个分隔符(由于filter(),它可以省略,但这将不必要地在匹配的单字符分隔符之间产生空字符串),以及filter(None,…)删除可能由前导和尾随分隔符创建的空字符串(因为空字符串具有假布尔值)。

正如问题标题中所要求的,这个re.split()精确地“使用多个分隔符进行拆分”。

此外,该解决方案不受其他一些解决方案中单词中非ASCII字符的问题的影响(参见ghostdog74答案的第一条注释)。

re模块比“手动”执行Python循环和测试更高效(速度和简洁)!

join = lambda x: sum(x,[])  # a.k.a. flatten1([[1],[2,3],[4]]) -> [1,2,3,4]
# ...alternatively...
join = lambda lists: [x for l in lists for x in l]

然后变成三行:

fragments = [text]
for token in tokens:
    fragments = join(f.split(token) for f in fragments)

解释

这就是Haskell中所谓的列表monad。monad背后的想法是,一旦“进入monad”,你就“留在monad”直到有什么东西把你带走。例如,在Haskell中,假设您将python range(n)->[1,2,…,n]函数映射到List上。如果结果是一个List,它将被附加到List中,所以你会得到类似map(range,[3,4,1])->[0,1,2,0,1,2,3,0]的结果。这被称为map append(或mappend,或类似的东西)。这里的想法是,你已经得到了你正在应用的这个操作(对一个令牌进行拆分),每当你这样做时,你都会将结果加入到列表中。

您可以将其抽象为一个函数,并在默认情况下使用token=string.p标点符号。

这种方法的优点:

这种方法(与基于正则表达式的简单方法不同)可以使用任意长度的令牌(正则表达式也可以使用更高级的语法)。你不仅仅局限于象征;您可以使用任意逻辑来代替每个标记,例如,其中一个“标记”可以是一个函数,该函数根据括号的嵌套程度进行拆分。

这是一个有一些解释的答案。

st = "Hey, you - what are you doing here!?"

# replace all the non alpha-numeric with space and then join.
new_string = ''.join([x.replace(x, ' ') if not x.isalnum() else x for x in st])
# output of new_string
'Hey  you  what are you doing here  '

# str.split() will remove all the empty string if separator is not provided
new_list = new_string.split()

# output of new_list
['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']

# we can join it to get a complete string without any non alpha-numeric character
' '.join(new_list)
# output
'Hey you what are you doing'

或者在一行中,我们可以这样做:

(''.join([x.replace(x, ' ') if not x.isalnum() else x for x in st])).split()

# output
['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']

更新的答案

实现这一点的另一种方法是使用自然语言工具包(nltk)。

import nltk
data= "Hey, you - what are you doing here!?"
word_tokens = nltk.tokenize.regexp_tokenize(data, r'\w+')
print word_tokens

这张照片显示:[“嘿”、“你”、“什么”、“是”、“您”、“正在做”、“在这里”]

这种方法的最大缺点是需要安装nltk包。

好处是,一旦获得令牌,就可以使用nltk包的其余部分做很多有趣的事情。

使用panda的series.str.split方法可以获得相同的结果,而不是使用re-module函数re.split。

首先,使用上述字符串创建一个系列,然后将该方法应用于该系列。

thestring=pd.Series(“嘿,你-你在这里干什么!?”)thestring.str.split(pat=',|-')

参数pat接受分隔符并将拆分字符串作为数组返回。这里,使用|(或运算符)传递两个分隔符。输出如下:

[嘿,你,你在这里干什么!?]