2012-03-21 505 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'] 

我從字面上只是寫了這個在約一個半小時所以我確信這個邏輯可以被清理。我也承認,它可能需要額外的邏輯來正確處理諸如連字符之類的警告,因爲它們的使用與諸如逗號之類的東西相比不一致。實際上,是否有任何模塊可以正確執行此操作?