Python:从不同大小和dtypes的单独列表中创建N维列表

时间:2017-07-25 18:49:49

标签: python arrays list numpy nested-loops

说我有这些清单:

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,&# 39; 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的维度执行此操作,并且许多嵌套for循环看起来似乎可能是构建此类数据结构的最佳或最有效的方法。我不能帮助,但认为必须有一个更好的解决方案,某些库中的某些东西,比如我上面编写的函数,可能是numpy函数,但是我做了很多搜索但没有找到列表的东西我有不同的大小和数据类型。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

您可以使用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,))

无需指定最后一个维度。

答案 1 :(得分:0)

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']