2013-02-13 67 views
2

總結了範圍我有一個整數列表:生成一個列表

list = [a,b,c,d] 

我想將它轉化成這些範圍:

0..a 
a+1..a+b 
a+b+1..a+b+c 
a+b+c+1..a+b+c+d 

任何想法如何做到這一點在Python?

感謝

+0

那些是你真正想要的範圍? – mgilson 2013-02-13 14:30:04

+0

請記住,你可能不想爲列表「list」命名,因爲它是一個內置的python對象。 – Hoopdady 2013-02-13 14:49:17

+0

@Hoopdady是的,謝謝你......我將它列入清單。 – bioinf80 2013-02-13 14:58:50

回答

9

一個簡單的發電機會做:

def to_ranges(seq): 
    iseq = iter(seq) 
    x = next(iseq) 
    yield range(0,x+1) 
    start = x 
    for x in iseq: 
     stop = start+x 
     yield range(start+1,stop+1) 
     start = stop 


for x in to_ranges([1,2,3,4]): 
    print x 

這給:

[0, 1]   #0 .. a check 
[2, 3]   #a+1 (2) .. a+b (1+2=3) check 
[4, 5, 6]  #a+b+1 (1+2+1=4) .. a+b+c (1+2+3=6) check 
[7, 8, 9, 10] #a+b+c+1 (1+2+3+1=7) .. a+b+c+d (1+2+3+4=10) check 

終於得到了它的權利。這裏不幸的是,第一個循環由於0邊界條件是特殊的 - 所以我們只需要展開那個,所有的東西都是對的。

+0

我還沒有喝完早上的咖啡,但是這似乎沒有產生OP要求的結果。 – DSM 2013-02-13 14:30:17

+0

@DSM - 是的。看我的編輯。 – mgilson 2013-02-13 14:33:04

+0

+1,但還有一個+1缺少'(a * + 1 * ... a + b)'? – root 2013-02-13 14:34:37

0

儘管接受的答案會產生正確的結果,但只需使用幾個循環和列表生成器即可獲得解決方案。 更高級的語言運算符看起來不合適,因爲問題是詢問這樣一個簡單的問題 - 生成一些列表。

此解決方案僅適用於正整數。 帶負片的處理序列留給讀者練習。

# starting data 
nums = [3, 5, 22, 6] 

# Generate endpoints for output sequences. 
# Note that the first sequence starts specially at 0. 
endpoints = [0] 
for i in range(len(nums)): 
    endpoints.append(endpoints[i] + nums[i]) 
endpoints[0] = -1 

# Generate output sequences. 
outseqs = [] 
for i in range(1, len(endpoints)): 
    outseq = [n for n in range(endpoints[i - 1] + 1, endpoints[i] + 1)] 
    outseqs.append(outseq) 

# Display output sequences. 
for i in range(len(outseqs)): 
    print outseqs[i] 
+0

對於'[1,2,3,4]'作爲輸入,例如,您的代碼會生成[[0],[1,2],[3,4,5],[6,7,8,9 ]]'。相反,它應該是'[[0,1],[2,3],[4,5,6],[7,8,9,10]] – pemistahl 2013-02-13 17:33:40

+0

@PeterStahl固定。 – 2013-02-13 17:36:04

+0

是的,現在它工作。但是,您的解決方案也會因爲它不適用於輸入中的負數而受到影響。 – pemistahl 2013-02-13 17:50:25

0

所有到目前爲止所提供的解決方案,如果是這樣,在相反的順序範圍須有輸入負數不起作用。我的解決方案涵蓋。與Python 2和3的工作在這裏:

from itertools import izip 

# create the x (=start) and y (=stop) coordinates for the ranges separately 
def _get_xs(iterable): 
    yield 0 
    for i in xrange(1, len(iterable)): 
     yield sum(iterable[:i]) + 1 

def _get_ys(iterable): 
    yield iterable[0] 
    for i in xrange(1, len(iterable)): 
     yield sum(iterable[:i+1]) 

def to_ranges(iterable): 
    xs = _get_xs(iterable) 
    ys = _get_ys(iterable) 
    for x, y in izip(xs, ys): 
     if x < y: 
      step = 1 
      y += 1 
     elif x > y: 
      step = -1 
      y -= 1 
     else: 
      step = 0 
     try: 
      yield range(x, y, step) 
     except ValueError: 
      yield [x] 

例子:

# edge case: instead of malformed ranges such as range(10, 10), put [10] instead 

>>> list(to_ranges([1, 2, 3, 4])) 
[[0, 1], [2, 3], [4, 5, 6], [7, 8, 9, 10]] 

>>> list(to_ranges([4, 3, 2, 1])) 
[[0, 1, 2, 3, 4], [5, 6, 7], [8, 9], [10]] 

>>> list(to_ranges([4, 3, 2, -1])) 
[[0, 1, 2, 3, 4], [5, 6, 7], [8, 9], [10, 9, 8]] 

>>> list(to_ranges([-4, -3, -2, -1])) 
[[0, -1, -2, -3, -4], [-3, -4, -5, -6, -7], [-6, -7, -8, -9], [-8, -9, -10]] 

>>> list(to_ranges([-1, -2, -3, -4])) 
[[0, -1], [0, -1, -2, -3], [-2, -3, -4, -5, -6], [-5, -6, -7, -8, -9, -10]]