2012-03-21 725 views
5

我试图将字符串分成单词,删除空格和标点符号。使用split()分割字符串中的各种标点符号

我尝试使用split()方法,将所有的标点一次,但我的结果是不正确的:

>>> test='hello,how are you?I am fine,thank you. And you?' 
>>> test.split(' ,.?') 
['hello,how are you?I am fine,thank you. And you?'] 

我确实知道如何与正则表达式已经这样做了,但我想弄清楚如何使用split()来做到这一点。请不要给我一个正则表达式解决方案。

+2

所以你坚持用锤子在手边时用扳手来打钉子。为什么? – 2012-03-21 01:24:22

+0

对OP没有任何不敬的含义我认为应该为这类问题添加一个标签,在这些问题中,无论出于何种原因(有时是有效的),适当的工具都会被忽略,它们会不时出现。也许'luddism'? – 2012-03-21 01:35:50

+0

试一试C#“你好,你好吗?我很好,谢谢。你呢?”分割(“,?。”。ToCharArray(),StringSplitOptions.RemoveEmptyEntries); – 2012-03-21 01:43:39

回答

10

这是不使用re模块我能想到的最好的办法:

"".join((char if char.isalpha() else " ") for char in test).split() 
+0

Ooo,这是另一种方式,虽然它不使用明确的分割字符列表... – larsks 2012-03-21 01:26:10

+0

你的代码更好,它可以处理其他标点符号 – leisurem 2012-03-23 06:11:50

+0

这很棒。虽然,与使用re.split相比效率稍差。 – 2016-09-11 15:49:19

11

如果你想将一个字符串分解基于多个分隔符,因为在你的榜样,你将需要使用re模块尽管你离奇的反对,这样的:

>>> re.split('[?.,]', test) 
['hello', 'how are you', 'I am fine', 'thank you', ' And you', ''] 

这是可能使用split获得类似结果,但是您需要为每个字符调用一次分割,并且需要遍历前一个分割的结果。这工作,但它的U-G-L-Y:

>>> sum([z.split() 
... for z in sum([y.split('?') 
... for y in sum([x.split('.') 
... for x in test.split(',')],[])], [])], []) 
['hello', 'how', 'are', 'you', 'I', 'am', 'fine', 'thank', 'you', 'And', 'you'] 

这使用sum()弄平前一次迭代返回的列表。

+0

请不要使用'sum()'来展平列表 - [这是为此目的的错误工具](http://stackoverflow.com/questions/952914/making-a-flat-list-out-的列表 - - 列表功能于蟒/ 952952#952952)。在这种情况下更是如此,因为[使用嵌套循环的单个列表理解](http://ideone.com/xEXX7)将首先消除平坦化的必要性。 – 2012-03-21 12:39:55

+0

如果您认为它更适合该问题,欢迎您发布备用解决方案。 – larsks 2012-03-21 13:04:42

+0

只要OP没有解释为什么不应该使用're',我不会发表一个答案,因为我不明白这个问题的目的。不过,我上次评论中的第二个链接显示了另一种解决方案。 – 2012-03-21 13:25:22

6

既然你不想使用重模块,您可以使用此:

test.replace(',',' ').replace('.',' ').replace('?',' ').split() 
+0

test ='你好,你好吗?我很好,谢谢你。你呢?' 用于测试X: 如果不是x.isalpha():试验= test.replace(X,”“) 测试= test.split() 打印测试 – leisurem 2012-03-23 06:07:10

3

您可以编写一个函数来扩展.split()用法:

def multi_split(s, seprators): 
    buf = [s] 
    for sep in seprators: 
     for loop, text in enumerate(buf): 
      buf[loop:loop+1] = [i for i in text.split(sep) if i] 
    return buf 

和尝试:

>>> multi_split('hello,how are you?I am fine,thank you. And you?', ' ,.?') ['hello', 'how', 'are', 'you', 'I', 'am', 'fine', 'thank', 'you', 'And', 'you']

这将更加清晰,可以在其他情况下使用。

3

larsks'的答案,在这里你不需要自己输入所有的标点字符的修改版本:

import re, string 

re.split("[" + string.punctuation + "]+", test) 
['hello', 'how are you', 'I am fine', 'thank you', ' And you', ''] 
0

道歉necroing - 这个主题上来,作为非正则表达式分裂的第一个结果一句话。看到我不得不为我的学生提出一个非Python特有的方法,并且这个线程没有回答我的问题,我想我会分享以防万一。

代码的点是不使用的库(和它的快速上的大文件):

sentence = "George Bernard-Shaw was a fine chap, I'm sure - who can really say?" 
alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 
words = [] 
word = "" 
mode = 0 
for ch in sentence: 
    if mode == 1: 
     words.append(word) 
     word = "" 
     mode = 0 
    if ch in alpha or ch == "'" or ch == "-": 
     word += ch 
    else: 
     mode = 1 
words.append(word) 
print(words) 

输出:

['George', 'Bernard-Shaw', 'was', 'a', 'fine', 'chap', "I'm", 'sure', '-', 'who', 'can', 'really', 'say'] 

我从字面上只是写了这个在约一个半小时所以我确信这个逻辑可以被清理。我也承认,它可能需要额外的逻辑来正确处理诸如连字符之类的警告,因为它们的使用与诸如逗号之类的东西相比不一致。实际上,是否有任何模块可以正确执行此操作?

相关问题