Python 中的嵌套列表理解
Nested list comprehension in Python
我有一个列表理解力,我正在努力理解,但我似乎无法理解我所追求的,我想看看是否有其他人知道如何做!
我的基本数据结构是这样的:
structure = [[np.array([[1,2,3],[4,5,6]]), np.array([[7,8,9],[10,11,12]])], [np.array([[13,14,15],[16,17,18]]), np.array([[19,20,21],[22,23,24]])]]
所以我得到了一个包含 numpy 数组子列表的整体列表,我想要的输出是某种分组(不管它是列表还是数组)与以下元素配对:
[1, 13]
[4, 16]
[2, 14]
[5, 17]
[3, 15]
[6, 18]
我以为我会通过以下样式构造得到它:
output = [structure[i][0][j] for j in range(9) for i in range(len(structure))]
可惜,没有快乐。
我真的不介意它是否需要多个阶段 - 只是想将这些元素组合在一起!
(作为背景知识——我有各种模型输出的概率列表,在这些模型中我有一个训练列表和一个验证列表:
[[model_1], [model_2], ..., [model_n]]
其中 [model_1]
是 [[training_set], [validation_set], [test_set]]
并且[training_set]
是np.array([p_1, p_2, ..., p_n],[p_1, p_2, ..., p_n],...])
我想将每个模型的项目 1 的预测组合在一起,并从中创建一个长度等于我拥有的模型数量的训练向量。然后我想做同样的事情,但对于 [training_set].
的第二行
如果这没有意义,请告诉我!
不确定您想要什么完整输出,但这可能会有所帮助:
imort numpy as np
structure = [[np.array([[1, 2, 3], [4, 5, 6]]), np.array([[7, 8, 9], [10, 11, 12]])],
[np.array([[13, 14, 15], [16, 17, 18]]), np.array([[19, 20, 21], [22, 23, 24]])]]
from itertools import chain
zipped = (zip(*ele) for ele in zip(*next(zip(*structure))))
print (list(chain.from_iterable(zip(*zipped))))
[(1, 13), (4, 16), (2, 14), (5, 17), (3, 15), (6, 18)]
好的巫术分解:
# transpose sub arrays so column 0 is the first two sub elements from
# each sub array
In [4]: start = zip(*structure)
In [5]: start
Out[5]:
[(array([[1, 2, 3],
[4, 5, 6]]), array([[13, 14, 15],
[16, 17, 18]])), (array([[ 7, 8, 9],
[10, 11, 12]]), array([[19, 20, 21],
[22, 23, 24]]))]
# our interesting sub array's i.e colunm[0]
In [6]: first_col = next(start)
In [7]: first_col
Out[7]:
(array([[1, 2, 3],
[4, 5, 6]]), array([[13, 14, 15],
[16, 17, 18]]))
# pair up corresponding sub array's
In [8]: intersting_pairs = zip(*first_col)
In [9]: intersting_pairs
Out[9]:
[(array([1, 2, 3]), array([13, 14, 15])),
(array([4, 5, 6]), array([16, 17, 18]))]
# pair them up (1, 13), (2, 14) ...
In [10]: create_final_pairings = [zip(*ele) for ele in intersting_pairs]
In [11]: create_final_pairings
Out[11]: [[(1, 13), (2, 14), (3, 15)], [(4, 16), (5, 17), (6, 18)]]
最后将所有链接到一个平面列表中并获得正确的顺序:
In [13]: from itertools import chain
# create flat list
In [14]: flat_list = list(chain.from_iterable(zip(*create_final_pairings))
In [15]: flat_list
Out[15]: [(1, 13), (4, 16), (2, 14), (5, 17), (3, 15), (6, 18)]
一个使用 zip 进行转置的简单示例可能会有所帮助:
In [17]: l = [[1,2,3],[4,5,6]]
In [18]: zip(*l)
Out[18]: [(1, 4), (2, 5), (3, 6)]
In [19]: zip(*l)[0]
Out[19]: (1, 4)
In [20]: zip(*l)[1]
Out[20]: (2, 5)
In [21]: zip(*l)[2]
Out[21]: (3, 6)
对于python2你可以使用itertools.izip:
from itertools import chain, izip
zipped = (izip(*ele) for ele in izip(*next(izip(*structure))))
print (list(chain.from_iterable(izip(*zipped))))
[(1, 13), (4, 16), (2, 14), (5, 17), (3, 15), (6, 18)]
我不得不先写非列表理解版本来解决这个问题:
new_training_vector = []
for m1, m2 in zip(structure[0], structure[1]):
for t1, t2 in zip(m1, m2):
for d1, d2 in zip(t1, t2):
new_training_vector.append([d1, d2])
它的工作方式是创建两个并行迭代器(使用 zip
),每个模型一个,然后为每个训练集创建两个并行迭代器,依此类推,直到我们得到实际数据并且可以将它们粘在一起。
一旦我们有了它,就不难将它折叠成列表理解:
new_training_vector = [[d1, d2]
for m1, m2 in zip(structure[0], structure[1])
for t1, t2 in zip(m1, m2)
for d1, d2 in zip(t1, t2)]
您也可以使用字典来执行此操作,如果出于某种原因这样做效果更好的话。但是您会丢失订单:
import collections
d = collections.defaultdict(list)
for model in structure:
for i, training_set in enumerate(model):
for j, row in enumerate(training_set):
for k, point in enumerate(row):
d[(i, j, k)].append(point)
这个的诀窍是我们只跟踪我们看到每个点的位置(模型级别除外),因此它们会自动进入相同的 dict
项目。
我认为这就是您想要的格式,它使用生成器:
</p>
<pre><code>import numpy as np
structure = [[np.array([[1,2,3],[4,5,6]]), np.array([[7,8,9],[10,11,12]])], [np.array([[13,14,15],[16,17,18]]), np.array([[19,20,21],[22,23,24]])]]
struc = structure
my_gen = ([struc[i][j][k][l], struc[i+1][j][k][l]] for i in range(len(struc)-1)
for j in range(len(struc[i]))
for k in range(len(struc[i][j]))
for l in range(len(struc[i][j][k])))
try:
val = my_gen.next()
while val != None:
print val
val = my_gen.next()
except:
pass
由于 structure
中的所有数组(和子列表)大小相同,您可以将其转换为一个更高维的数组:
In [189]: A=np.array(structure)
Out[189]:
array([[[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]],
[[[13, 14, 15],
[16, 17, 18]],
[[19, 20, 21],
[22, 23, 24]]]])
In [190]: A.shape
Out[190]: (2, 2, 2, 3)
重塑和交换轴可以给你各种组合。
例如,示例子列表中的值可以通过以下方式选择:
In [194]: A[:,0,:,:]
Out[194]:
array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[13, 14, 15],
[16, 17, 18]]])
并重塑得到
In [197]: A[:,0,:,:].reshape(2,6)
Out[197]:
array([[ 1, 2, 3, 4, 5, 6],
[13, 14, 15, 16, 17, 18]])
并转置得到 6 行对:
In [198]: A[:,0,:,:].reshape(2,6).T
Out[198]:
array([[ 1, 13],
[ 2, 14],
[ 3, 15],
[ 4, 16],
[ 5, 17],
[ 6, 18]])
为了让它们按 1,4,2,5..
顺序排列,我可以先转置
In [208]: A[:,0,:,:].T.reshape(6,2)
Out[208]:
array([[ 1, 13],
[ 4, 16],
[ 2, 14],
[ 5, 17],
[ 3, 15],
[ 6, 18]])
我有一个列表理解力,我正在努力理解,但我似乎无法理解我所追求的,我想看看是否有其他人知道如何做!
我的基本数据结构是这样的:
structure = [[np.array([[1,2,3],[4,5,6]]), np.array([[7,8,9],[10,11,12]])], [np.array([[13,14,15],[16,17,18]]), np.array([[19,20,21],[22,23,24]])]]
所以我得到了一个包含 numpy 数组子列表的整体列表,我想要的输出是某种分组(不管它是列表还是数组)与以下元素配对:
[1, 13]
[4, 16]
[2, 14]
[5, 17]
[3, 15]
[6, 18]
我以为我会通过以下样式构造得到它:
output = [structure[i][0][j] for j in range(9) for i in range(len(structure))]
可惜,没有快乐。
我真的不介意它是否需要多个阶段 - 只是想将这些元素组合在一起!
(作为背景知识——我有各种模型输出的概率列表,在这些模型中我有一个训练列表和一个验证列表:
[[model_1], [model_2], ..., [model_n]]
其中 [model_1]
是 [[training_set], [validation_set], [test_set]]
并且[training_set]
是np.array([p_1, p_2, ..., p_n],[p_1, p_2, ..., p_n],...])
我想将每个模型的项目 1 的预测组合在一起,并从中创建一个长度等于我拥有的模型数量的训练向量。然后我想做同样的事情,但对于 [training_set].
的第二行如果这没有意义,请告诉我!
不确定您想要什么完整输出,但这可能会有所帮助:
imort numpy as np
structure = [[np.array([[1, 2, 3], [4, 5, 6]]), np.array([[7, 8, 9], [10, 11, 12]])],
[np.array([[13, 14, 15], [16, 17, 18]]), np.array([[19, 20, 21], [22, 23, 24]])]]
from itertools import chain
zipped = (zip(*ele) for ele in zip(*next(zip(*structure))))
print (list(chain.from_iterable(zip(*zipped))))
[(1, 13), (4, 16), (2, 14), (5, 17), (3, 15), (6, 18)]
好的巫术分解:
# transpose sub arrays so column 0 is the first two sub elements from
# each sub array
In [4]: start = zip(*structure)
In [5]: start
Out[5]:
[(array([[1, 2, 3],
[4, 5, 6]]), array([[13, 14, 15],
[16, 17, 18]])), (array([[ 7, 8, 9],
[10, 11, 12]]), array([[19, 20, 21],
[22, 23, 24]]))]
# our interesting sub array's i.e colunm[0]
In [6]: first_col = next(start)
In [7]: first_col
Out[7]:
(array([[1, 2, 3],
[4, 5, 6]]), array([[13, 14, 15],
[16, 17, 18]]))
# pair up corresponding sub array's
In [8]: intersting_pairs = zip(*first_col)
In [9]: intersting_pairs
Out[9]:
[(array([1, 2, 3]), array([13, 14, 15])),
(array([4, 5, 6]), array([16, 17, 18]))]
# pair them up (1, 13), (2, 14) ...
In [10]: create_final_pairings = [zip(*ele) for ele in intersting_pairs]
In [11]: create_final_pairings
Out[11]: [[(1, 13), (2, 14), (3, 15)], [(4, 16), (5, 17), (6, 18)]]
最后将所有链接到一个平面列表中并获得正确的顺序:
In [13]: from itertools import chain
# create flat list
In [14]: flat_list = list(chain.from_iterable(zip(*create_final_pairings))
In [15]: flat_list
Out[15]: [(1, 13), (4, 16), (2, 14), (5, 17), (3, 15), (6, 18)]
一个使用 zip 进行转置的简单示例可能会有所帮助:
In [17]: l = [[1,2,3],[4,5,6]]
In [18]: zip(*l)
Out[18]: [(1, 4), (2, 5), (3, 6)]
In [19]: zip(*l)[0]
Out[19]: (1, 4)
In [20]: zip(*l)[1]
Out[20]: (2, 5)
In [21]: zip(*l)[2]
Out[21]: (3, 6)
对于python2你可以使用itertools.izip:
from itertools import chain, izip
zipped = (izip(*ele) for ele in izip(*next(izip(*structure))))
print (list(chain.from_iterable(izip(*zipped))))
[(1, 13), (4, 16), (2, 14), (5, 17), (3, 15), (6, 18)]
我不得不先写非列表理解版本来解决这个问题:
new_training_vector = []
for m1, m2 in zip(structure[0], structure[1]):
for t1, t2 in zip(m1, m2):
for d1, d2 in zip(t1, t2):
new_training_vector.append([d1, d2])
它的工作方式是创建两个并行迭代器(使用 zip
),每个模型一个,然后为每个训练集创建两个并行迭代器,依此类推,直到我们得到实际数据并且可以将它们粘在一起。
一旦我们有了它,就不难将它折叠成列表理解:
new_training_vector = [[d1, d2]
for m1, m2 in zip(structure[0], structure[1])
for t1, t2 in zip(m1, m2)
for d1, d2 in zip(t1, t2)]
您也可以使用字典来执行此操作,如果出于某种原因这样做效果更好的话。但是您会丢失订单:
import collections
d = collections.defaultdict(list)
for model in structure:
for i, training_set in enumerate(model):
for j, row in enumerate(training_set):
for k, point in enumerate(row):
d[(i, j, k)].append(point)
这个的诀窍是我们只跟踪我们看到每个点的位置(模型级别除外),因此它们会自动进入相同的 dict
项目。
我认为这就是您想要的格式,它使用生成器:
</p>
<pre><code>import numpy as np
structure = [[np.array([[1,2,3],[4,5,6]]), np.array([[7,8,9],[10,11,12]])], [np.array([[13,14,15],[16,17,18]]), np.array([[19,20,21],[22,23,24]])]]
struc = structure
my_gen = ([struc[i][j][k][l], struc[i+1][j][k][l]] for i in range(len(struc)-1)
for j in range(len(struc[i]))
for k in range(len(struc[i][j]))
for l in range(len(struc[i][j][k])))
try:
val = my_gen.next()
while val != None:
print val
val = my_gen.next()
except:
pass
由于 structure
中的所有数组(和子列表)大小相同,您可以将其转换为一个更高维的数组:
In [189]: A=np.array(structure)
Out[189]:
array([[[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]],
[[[13, 14, 15],
[16, 17, 18]],
[[19, 20, 21],
[22, 23, 24]]]])
In [190]: A.shape
Out[190]: (2, 2, 2, 3)
重塑和交换轴可以给你各种组合。
例如,示例子列表中的值可以通过以下方式选择:
In [194]: A[:,0,:,:]
Out[194]:
array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[13, 14, 15],
[16, 17, 18]]])
并重塑得到
In [197]: A[:,0,:,:].reshape(2,6)
Out[197]:
array([[ 1, 2, 3, 4, 5, 6],
[13, 14, 15, 16, 17, 18]])
并转置得到 6 行对:
In [198]: A[:,0,:,:].reshape(2,6).T
Out[198]:
array([[ 1, 13],
[ 2, 14],
[ 3, 15],
[ 4, 16],
[ 5, 17],
[ 6, 18]])
为了让它们按 1,4,2,5..
顺序排列,我可以先转置
In [208]: A[:,0,:,:].T.reshape(6,2)
Out[208]:
array([[ 1, 13],
[ 4, 16],
[ 2, 14],
[ 5, 17],
[ 3, 15],
[ 6, 18]])