2011-07-05 67 views
1
m = re.match(r'(\d+)(?:-(\d+))?$', string) 
start = m.group(1) 
end = m.group(2) or start 
return list(range(int(start, 10), int(end, 10) + 1)) 

眼下,這是能夠處理字符串按以下格式,並將其轉換成一個列表...如何將不同格式的字符串轉換爲int列表? (蟒蛇)

「0-6」的結果[0,1,2,3,4 ,5,6]

「7」的結果[7]

反正我有可以改變符號,以便能夠處理按以下格式以及串...

「1 2 3 4 5'結果爲[1,2,3,4,5]

+0

問題可以這樣做有一個更好的標題。如果你從確定的意見開始,應該用正則表達式來完成,你通常不會得到正確的答案。用*你想要做什麼來標題,而不是*你認爲你想做什麼。 –

回答

6

正則表達式並不都是生命。在這種情況下,真的沒有理由使用正則表達式。試試這個,它已經結束了快兩倍,例如,肖恩·奇對樣本數據'0-6 2 3-6'to_num_list(所有數據我想它是約1.9倍和4.5倍的速度之間):

def included_numbers(s): 
    out = [] 
    for chunk in s.split(): 
     if '-' in chunk: 
      f, t = chunk.split('-') 
      out.extend(range(int(f), int(t)+1)) 
     else: 
      out.append(int(chunk)) 
    return out 
+0

+1我同意正則表達式是這個問題的矯枉過正。爲了處理不需要的字符,可以很容易地用'try:...來包裝相關的塊,除了ValueError:...'。 –

+0

您可以使用'set()'而不是'list',這樣如果用戶指定重疊的範圍,則結果不包含重複項。 – kindall

+2

@kindall:那也可以將它們命名爲'hash(i)is i' for'int'。我不會改變答案,但順序可能很重要 - 但如果合適,使用'set()'是一個非常好的主意。 –

1
m = re.match(r'(?:(\d+)(?:-(\d+))|(?:(\d+)(?:\s+|$))+)?$', string) 

然後,看在捕獲的組3

+0

儘管這會顯着增加複雜性,所以也許您應該單獨執行此操作。 – delnan

3

我會堅持以相同的符號,然後使用re.findall()來獲取所有的比賽。例如

import re 
def to_num_list(instr): 
    out = [] 
    for m in re.finditer(r'(\d+)(?:-(\d+))?', instr): 
     if m.group(2) == None: 
      out.append(int(m.group(1))) 
     else: 
      start = int(m.group(1)) 
      end = int(m.group(2)) 
      out.extend(xrange(start, end + 1)) 
    return out 

這會給你處理imputs如"1 2 3 10-15"以及能力。用法示例:

>>> to_num_list("0-6") 
[0, 1, 2, 3, 4, 5, 6] 
>>> to_num_list("10") 
[10] 
>>> to_num_list("1 3 5") 
[1, 3, 5] 
>>> to_num_list("1 3 5 7-10 12-13") 
[1, 3, 5, 7, 8, 9, 10, 12, 13] 

,並在輸入錯誤(這可能不一定是你想要的)跳躍:

>>> to_num_list("hello world 1 2 3") 
[1, 2, 3] 
>>> to_num_list("") 
[] 
>>> to_num_list("1 hello 2 world 3") 
[1, 2, 3] 
>>> to_num_list("1hello2") 
[1, 2] 
0

兩個輸入格式可以通過非貪婪正則表達式匹配(由指定的? *之後量詞):

m = re.match(r'^(\d+)[0-9\-\s]*?(\d+)?$', string) 

分別(1)和m.group(2)將始終提取第一數和最後號碼到m.group,或者如果只有一個單一的數,將匹配在組(1)中,

請參閱greedy vs non-greedy在python文檔中。

+0

如果輸入是「1 3 5 2」',該怎麼辦? –

+0

OP沒有詢問輸入格式。如果問題的意圖是處理任何數字列表,那麼您的一般解決方案在我的失敗的地方工作。但是,如果意圖是要像他的兩個示例一樣列出數字的升序列表,那麼我的正則表達式適用於所有情況,並且比您的解決方案更簡單。這是一個折衷。 – shelhamer

+0

公平點。我只是在工作的理由是,允許一個數字列表作爲輸入,但只需要一個升序列表並不是很好的設計,特別是當''1-5「'也被支持時。通常,推斷什麼是_actual_要求與明確規定相反是有用的。 –

0

如果你可以使用拆分,你可以簡化你的正則表達式,讓分割處理所有空格分隔的列表定義。

import re 

def answer(string): 
    m = re.match(r'(\d+)-(\d+)$', string) 

    if m: 
     start = m.group(1) 
     end = m.group(2) or start 
     return list(range(int(start), int(end) + 1)) 

    return map(int, string.split(' '))