在python中迭代未清除的维数组

时间:2014-06-19 02:54:12

标签: python generator

我有一些像这样的多维数组:

a= [[1,2],[2,4],[31,2]]

b= [[[1,2],[2,4],[31,2]],[[22,34],[322,323],[3454,544]]]

c= [[[[1,2],[2,4],[31,2]],[[22,34],[322,323],[3454,544]]],[[[1,2],[2,4],[31,2]],[[22,34],[322,323],[3454,544]]]]

现在我想将每个[x,y]对的值更改为[x,y-x],所需的结果:

a= [[1,0],[2,2],[31,-29]]    ==> [1,0] =  [1,(1-0)]

我尝试使用这样的生成器(灵感来自此answer):

def flatten(ary):
    for el in ary:
        if isinstance(el, int):
            yield ary
        else:
            for sub in flatten(el):
                yield sub

但它没有按预期工作。

如何解决?

注意:

可以相应地改变变换[x,y] to [x,y-x]的操作,例如

[x,y] ==> [x,x*y]可能是另一项操作。

所以我不想将操作硬编码到迭代中。

我想要这样的事情:

for x,y in flatten(ary):
  return x,y-x

然后,如果有必要,我只需将其更改为:

for x,y in flatten(ary):
  return x,y+x  # any operation I want

4 个答案:

答案 0 :(得分:1)

这是一种方法 - 它是一种递归函数,如果你有一个列表列表,你可以在每个级别找到它,如果是这样,那就更深入了解。如果您有元素列表,请执行(x,y)=(x,y-x)转换。

a= [[1,2],[2,4],[31,2]]

b= [[[3,3],[22,542]]]

c= [[[[1,33],[5,88]]]]

def flatten(l):
    for i, e in enumerate(l):
        if type(e) is list and type(e[0]) is list:
            flatten(e)
        else:
            x, y = e
            l[i] = (x, y-x)

>>> flatten(a)
[(1, 1), (2, 2), (31, -29)]
>>> flatten(b)
[[(3, 0), (22, 520)]]
>>> flatten(c)
[[[(1, 31), (5, 78)]]]

答案 1 :(得分:1)

使用funcy

>>> from funcy import chunks, iflatten
>>> a= [[1,2],[2,4],[31,2]]
>>>
>>> b= [[[3,3],[22,542]]]
>>>
>>> c= [[[[1,33],[5,88]]]]
>>> chunks(2, iflatten(a))
[[1, 2], [2, 4], [31, 2]]
>>> chunks(2, iflatten(b))
[[3, 3], [22, 542]]
>>> chunks(2, iflatten(c))
[[1, 33], [5, 88]]

你可以这样做:

>>> for x, y in chunks(2, iflatten(any)):
...     # your operations

答案 2 :(得分:1)

我只是在代码

下面改进了Martin Konecny的回答
def flatten(array, operation):

    for i, e in enumerate(array):
        if isinstance(e, (list, tuple)) and isinstance(e[0], (list, tuple)):
            flatten(e, operation)
        elif isinstance(e, (int, float)):
            array[0], array[1] = operation(array[0], array[1])
            break
        else:
            array[i] = operation(e[0], e[1])

a= [[1,2],[2,4],[31,2]]

b= [[[1,2],[2,4],[31,2]],[[22,34],[322,323],[3454,544]]]

c= [[[[1,2],[2,4],[31,2]],[[22,34],[322,323],[3454,544]]],[[[1,2],[2,4],[31,2]],[[22,34],[322,323],[3454,544]]]]

以及演示的结果:

>>> 
>>> flatten(a, lambda x, y: [x, y * x])
>>> a
[[1, 2], [2, 8], [31, 62]]
>>> flatten(b, lambda x, y: [x, y - x])
>>> b
[[[1, 1], [2, 2], [31, -29]], [[22, 12], [322, 1], [3454, -2910]]]
>>> flatten(c, lambda x, y: [x, y + x])
>>> c
[[[[1, 3], [2, 6], [31, 33]], [[22, 56], [322, 645], [3454, 3998]]], [[[1, 3], [2, 6], [31, 33]], [[22, 56], [322, 645], [3454, 3998]]]]
>>> 

这是新测试:

>>> 
>>> d = [1,2]
>>> flatten(d, lambda x, y: [x, y +5])
>>> d
[1, 7]
>>> 

希望,可以帮到你。

答案 3 :(得分:0)

使用funcy执行此操作的另一种方法。只需在适当的级别停止压扁:

from funcy import iflatten, is_list

follow = lambda l: is_list(l) and not is_list(l[0])
d = [(x, y - x) for x, y in iflatten(l, follow)]