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.])
        ]
    ]
]

(其中arrays 是numpy.arrays)

如何编写一个给我的生成器:

(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]]
4

3 回答 3

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
于 2012-10-02T08:09:44.327 回答
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东西是为了漂亮的印刷品,以便更接近你的例子。我不太确定用于检测叶子的标准。另请注意,我使用以下 pythonic 数组进行了实验:

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

而不是给出的 numpy 数组,但是使用 numarray 运行的更改应该很简单。

于 2012-10-01T23:52:10.343 回答
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, [] )计算。

于 2012-10-01T14:00:53.223 回答