【问题标题】:Python: Creating an N-dimensional list from separate lists of varying sizes and dtypesPython:从不同大小和 dtype 的单独列表创建 N 维列表
【发布时间】:2017-07-25 18:49:48
【问题描述】:

假设我有这些列表:

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

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

例如,假设 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 的维度执行此操作,而且许多嵌套的 for 循环似乎不可能是构建此类数据结构的最佳或最有效的方法。我不禁想到必须有一个更好的解决方案,在一些库中,比如我上面编写的函数,也许是 numpy 函数,但我做了很多搜索,没有找到不同大小的列表和像我这样的数据类型。

有什么想法吗?

【问题讨论】:

  • 所以,你想要itertools.product
  • list(itertools.product(a, b c)) 不会为您提供您正在寻找的嵌套,但除此之外它看起来很完美。而且,这很容易扩展。 lists = [a, b, c] 然后拨打list(itertools.product(*lists))。如果您稍后想添加第四个可迭代对象,您可以执行 lists.append(d) 并调用 list(itertools.product(*lists))
  • @cᴏʟᴅsᴘᴇᴇᴅ 分组到子列表不应该是问题的一部分吗?
  • @cᴏʟᴅsᴘᴇᴇᴅ:不是完全相同的副本,因为 OP 想要不同形状的结果。
  • 好吧,我的错。现在重新打开它。

标签: python arrays list numpy nested-loops


【解决方案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,))

无需指定最后一个维度。

【讨论】:

  • new_shape = list(map(len, args)) + [len(args)] 然后.reshape(*new_shape) 会使这个通用。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2021-08-24
    • 1970-01-01
    • 1970-01-01
    • 2017-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-10
    • 1970-01-01
    相关资源
    最近更新 更多