将列表拆分为嵌套列表中的子列表

时间:2017-02-09 12:32:42

标签: python numpy

我有一个列表l,方法如下:

l = [([1, 0.0, 50.0, 2, 0.0, 50.0], [1, 1.9, 1]),
     ([1, 0.0, 50.0, 2, 0.0, 50.0], [2, 1.9, 1])]

我想转换这个列表,以便新结构如下:

goal = [([1, 0.0, 50.0], [2, 0.0, 50.0], [1, 1.9, 1]), ([1, 0.0, 50.0], [2, 0.0, 50.0], [2, 1.9, 1])]

即,每个元组中的第一个列表会被解析为长度为3的子列表。

我尝试了以下方式,但因各种变换返回numpy数组而陷入困境。 此外,此操作可能会发生在l的大型变体上,因此应该是性能友好/就地(?)。

terms = np.array(l)[:,0]
[np.split(np.array(i), 2) for i in terms]

2 个答案:

答案 0 :(得分:1)

您可以在列表理解中使用itertools.chain

In [23]: from itertools import chain

In [24]: [tuple(chain.from_iterable((i[:3], i[3:]) if len(i) > 3 else [i] for i in sub)) for sub in l]
Out[24]: 
[([1, 0.0, 50.0], [2, 0.0, 50.0], [1, 1.9, 1]),
 ([1, 0.0, 50.0], [2, 0.0, 50.0], [2, 1.9, 1])]

作为一般方法,您可以使用itertools.islice将子列表分割为三元组:

In [37]: [tuple(list(islice(i,t,t+3)) if len(i) > 3 else i for i in sub for t in range(0, len(i), 3)) for sub in l]
Out[37]: 
[([1, 0.0, 50.0], [2, 0.0, 50.0], [1, 1.9, 1]),
 ([1, 0.0, 50.0], [2, 0.0, 50.0], [2, 1.9, 1])]

答案 1 :(得分:0)

在我的评论中,我反对使用np.array,因为

In [241]: np.array(l)
Out[241]: 
array([[[1, 0.0, 50.0, 2, 0.0, 50.0], [1, 1.9, 1]],
       [[1, 0.0, 50.0, 2, 0.0, 50.0], [2, 1.9, 1]]], dtype=object)

是一个对象数组。但是,阵列版本可以通过重塑

轻松拆分列表
In [240]: [np.array(x[0]+x[1]).reshape(-1,3).tolist() for x in l]
Out[240]: 
[[[1.0, 0.0, 50.0], [2.0, 0.0, 50.0], [1.0, 1.9, 1.0]],
 [[1.0, 0.0, 50.0], [2.0, 0.0, 50.0], [2.0, 1.9, 1.0]]]

如果必须是元组而不是列表,请添加[tuple(n...

我正在做一些技巧。由于第二个项目的长度与所需的分割(3)相同,我只是在开始时将它们连接起来,而不用担心以后会这样做。然后数组重新形成,然后tolist有效地拆分数组。

In [246]: np.reshape(x[0]+x[1],(-1,3))
Out[246]: 
array([[  1. ,   0. ,  50. ],
       [  2. ,   0. ,  50. ],
       [  1. ,   1.9,   1. ]])

这取决于能否将子列表均匀地拆分为3。

数组往返可能比等效的itertools代码慢。

in-place无效,因为您有一个元组列表。您可以替换这些元组,但不能修改它们。如果它们是列表,你可以像这样拼接拆分:

In [248]: x
Out[248]: ([1, 0.0, 50.0, 2, 0.0, 50.0], [1, 1.9, 1])
In [249]: xl=list(x)

In [250]: xl[0:1] = [xl[0][:3],xl[0][3:]]   # or the split of your choice
In [251]: xl
Out[251]: [[1, 0.0, 50.0], [2, 0.0, 50.0], [1, 1.9, 1]]

创建新列表和元组通常比更改现有内容更方便。复制列表列表只是意味着创建相同指针的新列表。

由于可以切换列表末尾@Kasramvd's islice版本可以简化为:

[tuple([i[t:t+3]  for i in sub for t in range(0, len(i), 3)]) for sub in l]