Python:从不同大小和dtype的单独列表创建一个N维列表



>假设我有这些列表:

a = [1, 2, 3, 4]
b = [6,7]
c = ['a', 'b', 'c']

我想创建一个包含新列表的三维数据结构,该结构以所有可能的方式将每个列表的所有元素组合在一起。然后我想使用类似索引的矩阵访问这些新列表。

例如,假设 f 是一个做我想做的事的函数。然后我可以这样做:

m = f(a,b,c)

然后 m[0][0][0] 会给出 [1,6,'a'],m[1][0][0] 会给出 [2,6,'a'],依此类推。

基本上,我知道我已经可以使用嵌套的 for 循环来做到这一点。

jList = []
for j in a:
kList = []
for k in b:
lList = []
for l in c:
o = [j,k,l]
lList.append(o)
kList.append(lList)
jList.append(kList)

这给了我一个列表列表的列表列表列表。

[[[[1, 6, 'a'], [1, 6, 'b'], [1, 6, 'c']], 
[[1, 7, 'a'], [1, 7, 'b'], [1, 7, 'c']]], 
[[[2, 6, 'a'], [2, 6, 'b'], [2, 6, 'c']], 
[[2, 7, 'a'], [2, 7, 'b'], [2, 7, 'c']]], 
[[[3, 6, 'a'], [3, 6, 'b'], [3, 6, 'c']], 
[[3, 7, 'a'], [3, 7, 'b'], [3, 7, 'c']]], 
[[[4, 6, 'a'], [4, 6, 'b'], [4, 6, 'c']], 
[[4, 7, 'a'], [4, 7, 'b'], [4, 7, 'c']]]]

这很好,但我必须为高于 3 的维度执行此操作,并且许多嵌套的循环似乎不可能是构建此类数据结构的最佳或最有效的方法。我不禁想到一定有一个更好的解决方案,在某些库中有一些东西,比如我上面编造的函数,也许是 numpy 函数,但我做了很多搜索,没有找到像我这样不同大小和数据类型的列表。

有什么想法吗?

您可以使用itertools.product获取列表的笛卡尔乘积,然后使用numpy.reshape进行重塑,从列表数中获取最后一个维度,然后到最内层列表的长度,直到最外层列表的长度:

>>> args = a,b,c
>>> np.array(list(product(*args))).reshape(len(a), len(b), len(c), len(args))
array([[[['1', '6', 'a'],
['1', '6', 'b'],
['1', '6', 'c']],
[['1', '7', 'a'],
['1', '7', 'b'],
['1', '7', 'c']]],

[[['2', '6', 'a'],
['2', '6', 'b'],
['2', '6', 'c']],
[['2', '7', 'a'],
['2', '7', 'b'],
['2', '7', 'c']]],

[[['3', '6', 'a'],
['3', '6', 'b'],
['3', '6', 'c']],
[['3', '7', 'a'],
['3', '7', 'b'],
['3', '7', 'c']]],

[[['4', '6', 'a'],
['4', '6', 'b'],
['4', '6', 'c']],
[['4', '7', 'a'],
['4', '7', 'b'],
['4', '7', 'c']]]],
dtype='<U21')

您可以使用以下方法动态生成形状:tuple(map(len, args)) + (len(args),)(由 @StevenRumbalski 建议(,因此您现在拥有:

>>> np.array(list(product(*args))).reshape(tuple(map(len, args)) + (len(args),))

或:

>>> np.array(list(product(*args))).reshape(tuple(map(len, args)) + (-1,))

无需指定最后一个维度。

Vanilla Python。

from itertools import product
a = [1, 2, 3, 4]
b = [6,7]
c = ['a', 'b', 'c']
data = [a,b,c]
dims = [range(len(i)) for i in data]
keys = product(*dims)
vals = (list(val) for val in product(*data))
space = dict(zip(keys,vals))
for key in space:
print "{} -> {}".format(key, space[key])
(3, 0, 2) -> [4, 6, 'c']
(0, 1, 1) -> [1, 7, 'b']
(0, 1, 2) -> [1, 7, 'c']
(1, 0, 1) -> [2, 6, 'b']
(1, 0, 0) -> [2, 6, 'a']
(2, 0, 1) -> [3, 6, 'b']
(2, 0, 0) -> [3, 6, 'a']
(3, 1, 0) -> [4, 7, 'a']
(3, 1, 1) -> [4, 7, 'b']
(0, 0, 2) -> [1, 6, 'c']
(2, 0, 2) -> [3, 6, 'c']
(0, 0, 1) -> [1, 6, 'b']
(0, 0, 0) -> [1, 6, 'a']
(2, 1, 2) -> [3, 7, 'c']
(1, 1, 1) -> [2, 7, 'b']
(1, 0, 2) -> [2, 6, 'c']
(1, 1, 0) -> [2, 7, 'a']
(2, 1, 0) -> [3, 7, 'a']
(2, 1, 1) -> [3, 7, 'b']
(1, 1, 2) -> [2, 7, 'c']
(3, 0, 0) -> [4, 6, 'a']
(3, 1, 2) -> [4, 7, 'c']
(3, 0, 1) -> [4, 6, 'b']
(0, 1, 0) -> [1, 7, 'a']

最新更新