2012-10-01 118 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