Pythonic将嵌套列表操作为嵌套的chunked列表的方法

时间:2014-09-29 14:32:24

标签: python list

我有一个列表,其嵌套列表的大小可能会以2的倍数变化。目前,在此示例中,嵌套列表的长度为4。

a_list = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]

根据长度,我试图打破列表,以最佳的pythonic方式得到以下结果:

a = [[1,2], [5,6], [9,10]]
b = [[3,4], [7,8], [11,12]]

如果嵌套列表的长度为6,那么

c = [[..], [..], [..]]

它是一种嵌套列表的转置,但在一行中有两组值不能转置。

5 个答案:

答案 0 :(得分:6)

使用列表理解:

>>> a_list = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
>>> a = [x[:2] for x in a_list]
>>> b = [x[2:] for x in a_list]
>>> a
[[1, 2], [5, 6], [9, 10]]
>>> b
[[3, 4], [7, 8], [11, 12]]

更一般的解决方案:

>>> [[x[i:i+2] for x in a_list] for i in range(0, len(a_list[0]), 2)]
[[[1, 2], [5, 6], [9, 10]],
 [[3, 4], [7, 8], [11, 12]]]

答案 1 :(得分:2)

我会毫不犹豫地称之为“pythonic”,因为它几乎难以辨认,但是:

>>> a, b = zip(*(zip(*[iter(s)]*2) for s in a_list))
>>> a
((1, 2), (5, 6), (9, 10))
>>> b
((3, 4), (7, 8), (11, 12))

也适用于6项目列表:

>>> a_list = [[1,2,3,4,100,102],[5,6,7,8,103,104],[9,10,11,12,105,106]]
>>> a, b, c = zip(*(zip(*[iter(s)]*2) for s in a_list))
>>> a
((1, 2), (5, 6), (9, 10))
>>> b
((3, 4), (7, 8), (11, 12))
>>> c
((100, 102), (103, 104), (105, 106))

答案 2 :(得分:1)

与falsetru的答案几乎相同,但首先将嵌套列表拆分为大小为2的块,然后将它们全部压缩在一起。

>>> a_list = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
>>> zip(*([j[i*2: i*2 + 2] for i in range(len(j) / 2)] for j in a_list))
[([1, 2], [5, 6], [9, 10]), ([3, 4], [7, 8], [11, 12])]

>>> a_list = [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]
>>> zip(*([j[i*2: i*2 + 2] for i in range(len(j) / 2)] for j in a_list))
[([1, 2], [7, 8]), ([3, 4], [9, 10]), ([5, 6], [11, 12])]

>>> a_list = [[1,2,3,4,100,102],[5,6,7,8,103,104],[9,10,11,12,105,106]]
>>> zip(*([j[i*2: i*2 + 2] for i in range(len(j) / 2)] for j in a_list))
[([1, 2], [5, 6], [9, 10]), ([3, 4], [7, 8], [11, 12]), ([100, 102], [103, 104], [105, 106])]

答案 3 :(得分:1)

快速方法是使用numpy.hsplit

>>> import numpy
>>> numpy.hsplit(numpy.array(a_list),2)
[array([[ 1,  2],[ 5,  6],[ 9, 10]]),array([[ 3,  4],[ 7,  8],[11, 12]])]

答案 4 :(得分:1)

由于可读性是pythonic,这里是一个更简单的基于迭代器的解决方案(没有@Zero用来将其变成单行的简洁技巧):

首先,将列表[1,2,3,4,5,6]转换为[(1, 2), (3, 4), (5, 6)]的迭代器。

def pairs(lst):
    it=iter(lst)
    return list(zip(it, it))   # Return a list of pairs drawn from the same iterator

列表a_list可以转换为这样的对列表的列表,如下所示:

a_list = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]    
pair_list = [ pairs(row) for row in a_list ]

最后,我们需要有效地转置这个列表,列出每个子列表中的第一对/元素,另一个列表中的第二个,等等。transposing a list的一个很好的习语是zip(*some_list) 。让我们使用它来进行OP请求的转换:

a, b = zip(*pair_list)

或在一个列表中收集任意数量的生成列表:

results = list( zip(*pair_list) )

随意将这些包装成一行(虽然我不会):

results = list(zip( *(pairs(row) for row in a_list) ))