2014-04-01 50 views
2

我想不出一個體面的標題,我很抱歉。我有一個輸入我想從用戶採取允許這樣的格式(字符串):如何將混合語法列表(範圍等)轉換爲單個列表?

1, 2,4, 9-13, 12, 3 

而且爲我提供了這樣一個整數列表:

[1, 2, 3, 4, 9, 10, 11, 12, 13] 

我可以想到一些可怕的方法來解決這個問題,我只是想知道是否有什麼「好」。我現在提交我的第一個想法作爲答案。

回答

2

那麼這是我的「手動」方式。它可以檢查像下面這樣的愚蠢行爲:-------1,但如果使用得當,它會起作用。

import re 
inp = '1, 2,4, 9-13, 12, 3' 
ret = [] 

for g in re.sub(r'[^\d,\-]', '', inp).split(','): 
    m = re.match('(-?\d+)-(-?\d+)', g) 

    if not m: 
     ret.append(int(g)) 
     continue 

    # we're talking about a range. 
    a, b = sorted([int(x) for x in m.groups()]) 
    ret += range(a, b+1) 

#de-dupe 
ret = list(set(ret)) 
+0

@Aशwiniचhaudhary你是完全正確的。在之前的迭代中,我加入了一個上界,但是在切割層上丟失了。 **編輯:**修正。 – Oli

+0

如果按照你想要的方式工作,我其實並不覺得太糟糕。一個小問題是:'sorted'需要一個迭代,所以你可以省略方括號(除非使用早於2.4的Python)。 –

2

事情是這樣的:

from itertools import chain 

def solve(s): 
    for x in s.split(','): 
     #Strip the trailing and leading spaces + '-' and then split at '-' only once. 
     d = x.strip(' -').split('-', 1) 
     if len(d) == 1: 
      yield [int(d[0])] 
     elif len(d) == 2: 
      s, e = sorted(map(int, d)) 
      yield range(s, e+1) 


print sorted(set(chain.from_iterable(solve('1--1, 2,4, 9-13, 12, 3')))) 
print sorted(set(chain.from_iterable(solve('1, 2,4, 9-14, 12, 3, ------14')))) 
print sorted(set(chain.from_iterable(solve('1, 2,4, -----6-----,9-14, 12, 3')))) 
print sorted(set(chain.from_iterable(solve('1, 2,4,11--11, -----6-----,9-14, 12, 3')))) 

輸出:

[-1, 0, 1, 2, 3, 4, 9, 10, 11, 12, 13] 
[1, 2, 3, 4, 9, 10, 11, 12, 13, 14] 
[1, 2, 3, 4, 6, 9, 10, 11, 12, 13, 14] 
[-11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] 
+0

yeilding進入鏈條不錯,但它目前不能很好地應付負數。考慮一下列表:'2,3,1-1'(應該輸出'-1,0,1,2,3')。地圖演員也比我的列表理解更有趣。 – Oli

+0

@Oli好吧,像'----------- 2'這樣的東西會被認爲是'-2'或'2'嗎? –

+0

我不會擔心這種有目的的破壞語法,但是「1--1」應該表示「一到一」。 – Oli