2012-10-01 167 views
2

我有這樣的結構:遍歷狀結構樹

[ 
    array([ 0. , 4.5, 9. ]), 
    [ 
     array([ 100., 120., 140.]), 
     [ 
      array([ 1000., 1100., 1200.]), 
      array([ 1200., 1300., 1400.]) 
     ], 
     array([ 150., 170., 190.]), 
     [ 
      array([ 1500., 1600., 1700.]), 
      array([ 1700., 1800.]) 
     ] 
    ] 
] 

(其中array s爲numpy.array S)

如何編寫一個生成器,給我:

(0, 4.5), (100, 120), (1000, 1100) 
(0, 4.5), (100, 120), (1100, 1200) 
(0, 4.5), (120, 140), (1200, 1300) 
(0, 4.5), (120, 140), (1300, 1400) 
(4.5, 9), (150, 170), (1500, 1600) 
(4.5, 9), (150, 170), (1600, 1700) 
(4.5, 9), (170, 190), (1700, 1800) 

到目前爲止,我唯一擁有的是:

def loop_bin(bins): 
    for i in range(len(bins)-1): 
     yield [bins[i], bins[i+1]] 
+0

什麼是*數組* *?爲什麼第3行和第4行是相同的? – hochl

+0

'array'是'np.array' –

+0

您是否知道itertools? http://docs.python.org/library/itertools.html –

回答

1

什麼:

def foo(m): 

    for i in range(0, len(m), 2): 

    for j in range(len(m[i])-1): 
     current = tuple(m[i][j:(j+2)]) 
     mm = m[i+1] 
     if(len(mm) % 2 != 0 or (len(mm) > 1 and not type(mm[1][0]) is types.ListType)): 
     currentl = mm[j] 
     for k in range(0, len(currentl)-1): 
      yield current, tuple(currentl[k:(k+2)]) 

     else: 
     for res in foo(mm[2*j:2*j+2]): 
      # this is for pretty print only 
      if type(res) is types.TupleType and len(res)>1 and not type(res[0]) is types.TupleType: 
      yield current, res 
      else: 
      # pretty print again 
      c = [current] 
      c+= res 
      yield tuple(c) 

tuple事情是相當的打印,以獲得更接近你的榜樣。我不太確定用於檢測葉子的標準。還要注意,我做我的實驗用下面的Python的數組:

arr = [ 
    [ 0. , 4.5, 9. ], 
    [ 
     [100., 120., 140.], 
     [ 
      [ 1000., 1100., 1200.], 
      [ 1200., 1300., 1400.] 
     ], 
     [ 150., 170., 190.], 
     [ 
      [ 1500., 1600., 1700.], 
      [ 1700., 1800.] 
     ] 
    ] 
] 

,而不是給出的numpy的陣列,但變化得到的東西與numarray運行應該直截了當。

0

使用遞歸來做到這一點:

def foo(lst, path): 
    if type(lst[0]) != type(array([])): 
     return [path+[(lst[0],lst[1])], path+[(lst[1],lst[2])]] 

    i = 0 
    ret = [] 
    while i < len(lst): 
     node = lst[i] 
     successor = lst[i+1] if i+1<len(lst) else None 
     if type(node) == type(array([])): 
      if type(successor) == list: 
       children = successor 
       ret.extend(foo(children, path + [(node[0], node[1])])) 
       ret.extend(foo(children, path + [(node[1], node[2])])) 
       i+=1 
      else: 
       ret.append(path + [(node[0], node[1])]) 
       ret.append(path + [(node[1], node[2])]) 
     i+=1 
    return ret 

呼叫foo(input, [])來計算。

+0

這產生了32個項目而不是8個。 –

+0

@tobias_k,是的,但我想知道樣本列表是否完整。 – Marcus

+0

輸出錯誤 –

2

看着你的情況我已經把它分解成幾種不同類型的迭代:overlappaired(以及常規迭代)。

然後,我遞歸遍歷你的樹結構dopair,它分析類型以決定它應該如何遍歷它所看到的數據。這個決定是基於我們是處理一個節點(包含一個子樹)還是一個葉子(一個數組)。

generator踢它一切。 izip允許我們同時迭代兩個生成器。

from itertools import izip 

class array(list): 
    pass 

arr = [ 
    array([ 0. , 4.5, 9. ]), 
    [ 
     array([100., 120., 140.]), 
     [ 
      array([ 1000., 1100., 1200.]), 
      array([ 1200., 1300., 1400.]) 
     ], 
     array([ 150., 170., 190.]), 
     [ 
      array([ 1500., 1600., 1700.]), 
      array([ 1700., 1800.]) 
     ] 
    ] 
] 

# overlap(structure) -> [st, tr, ru, uc, ct, tu, ur, re] 
def overlap(structure): 
    for i in range(len(structure)-1): 
     yield (structure[i],structure[i+1]) 

# paired(structure) -> [st, ru, ct, ur] 
def paired(structure): 
    for i in range(0,len(structure)-1,2): 
     yield (structure[i],structure[i+1]) 

def dopair(first,second): 
    if all(isinstance(x,array) for x in second): 
     for pa,ir in izip(overlap(first),second): 
      for item in overlap(ir): 
       yield pa, item 
    else: 
     for pa,(i,r) in izip(overlap(first),paired(second)): 
      for item in dopair(i,r): 
       yield (pa,) + item 

def generator(arr): 
    for pa,ir in paired(arr): 
     for x in dopair(pa,ir): 
      yield x 

for x in generator(arr): 
    print x