2010-05-20 155 views
2

我在尋找最有效的方式將元素添加到一個逗號分隔的字符串,同時保持單詞字母順序刪除元素:有效的方式從一個逗號分隔的字符串

例如:

string = 'Apples, Bananas, Grapes, Oranges' 
subtraction = 'Bananas' 
result = 'Apples, Grapes, Oranges' 

此外,一種方法可以做到這一點,但同時保持編號:

string = '1:Apples, 4:Bananas, 6:Grapes, 23:Oranges' 
subtraction = '4:Bananas' 
result = '1:Apples, 6:Grapes, 23:Oranges' 

示例代碼是極大的讚賞。非常感謝。

+1

你真的需要使用字符串作爲數據結構,或者你可以有一本字典或設置在幕後,只是*打印*作爲一個逗號分隔的字符串? – 2010-05-20 08:01:54

+0

不幸的是,它是一個要求:(。謝謝但 – ensnare 2010-05-20 08:08:40

+0

我看不出你提供的兩種情況之間的區別,也許你的意思是你想保留*字母*順序,儘管ID在前面,而不是在相同的順序?但是,如果排序順序是正確的,那麼兩種情況是相同的。 – UncleZeiv 2010-05-20 09:30:52

回答

1

理想的情況下,這樣的:

input_str = '1:Apples, 4:Bananas, 6:Grapes, 23:Oranges' 
removal_str = '4:Bananas' 
sep = ", " 

print sep.join(input_str.split(sep).remove(removal_str)) 

會工作。但是Python不返回從刪除()新的列表,所以你不能這樣做,所有在同一行,而需要臨時變量等類似的解決方案,它的工作是:

input_str = '1:Apples, 4:Bananas, 6:Grapes, 23:Oranges' 
removal_str = '4:Bananas' 
sep = ", " 

print sep.join([ i for i in input_str.split(sep) if i != removal_str ]) 

然而,儘可能正確,假設你沒有保證所有項目都是有效的,你需要驗證每個項目是否符合給予你的所有規範,即它們是格式編號:標識符。最簡單的方法是使用re模塊搜索特定的正則表達式格式,返回所有結果,並跳過與所需結果不匹配的結果。使用故意緊湊的代碼,你會得到一個合理的短期解決方案,它很好的驗證:

def str_to_dictlist(inp_str): 
    import re 
    regexp = r"(?P<id>[0-9]+):(?P<name>[a-zA-Z0-9_]+)" 
    return [ x.groups() for x in re.finditer(regexp, inp_str) ] 

input_str = '1:Apples, 4:Bananas, 6:Grapes, 23:Oranges' 
subtraction_str = "4:Bananas" 
sep = ", " 

input_items = str_to_dictlist(input_str) 
removal_items = str_to_dictlist(subtraction_str) 
final_items = [ "%s:%s" % (x,y) for x,y in input_items if (x,y) not in removal_items ] 

print sep.join(final_items) 

這也讓在同一時間處理多個清除的優勢。由於輸入格式和刪除格式非常相似,並且輸入格式有多個項目,因此刪除格式可能也需要支持它們 - 或者至少有這種支持是有用的。

注意,這樣做(重新使用搜索)這種方式將使其難以檢測不過不要驗證項目;它只會掃描任何事情。作爲一個黑客,你可以指望在輸入逗號和報告的東西可能無法解析警告:

if items_found < (num_commas + 1): 
    print warning_str 

這將警告逗號沒有空格爲好。

要正確解析更復雜的輸入字符串,您需要將其分解爲單獨的標記,在解析時跟蹤輸入行和列,爲意外事件打印錯誤,甚至可以處理諸如回溯和圖形構建之類的內容以獲取更多複雜的輸入,如源代碼。對於這類東西,請查看pyparsing模塊(這是第三方下載;它不包含python)。

0
>>> import re 
>>> re.sub("Bananas, |, Bananas$", "", "Apples, Bananas, Grapes, Oranges") 
'Apples, Grapes, Oranges' 

import re 
strng = '1:Apples, 4:Bananas, 6:Grapes, 23:Oranges' 
subtraction = '4:Bananas' 
result = re.sub(subtraction + ", |, " + subtraction, "", strng) 
print result 

這適用於你的例子,但需要進行修改,如果減法字符串可能包含如下[].*?{}\正則表達式元字符。

正如一位評論者指出的那樣,這是一個低級別的字符串操作。它可能正常工作,但考慮到數據結構的方法應該更可靠。在逗號/空格分割是否足夠,或者您是否需要csv模塊的健壯性取決於您期望的可能輸入字符串。

+0

我沒有認爲這處理了第一個/最後一個項目是要被刪除的情況,換句話說,它不是將輸入視爲數據列表(如指定的那樣),而是將其視爲低級別的字符串 – 2010-05-20 09:34:32

+0

它確實處理了第一個案例;我現在已經修改了它也處理了最後,但我與你,這需要更高層次的結構考慮的一個方法可能是最好同意在規範,輸入*是*字符串,而不是一個名單,雖然。 – 2010-05-20 10:07:06

1

上述馬修的評論是正確的做法,但如果你是確保,(逗號後面有一個空格)發生作爲分隔符,那麼像這樣的工作

def remove(str, element): 
    items = str.split(", ") 
    items.remove(element) 
    return ", ".join(items) 

我不會」不過建議你使用字符串作爲列表。他們是爲不同的目的而設計的,遵循Matthew的建議是正確的。