Вопрос по python-2.7, python, list, list-comprehension – Python 2.7 создает многомерный список

14

В Python я хочу интуитивно понятный способ создания трехмерного списка.

Я хочу (n на n) список. Таким образом, для n = 4 это должно быть: I '

x = [[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]]

мы пробовали использовать:

y = [n*[n*[]]]    
y = [[[]]* n for i in range(n)]

Которые оба, кажется, создают копии ссылки. Я'Мы также с небольшим успехом попробовали наивное приложение построителя списка:

y = [[[]* n for i in range(n)]* n for i in range(n)]
y = [[[]* n for i in range(1)]* n for i in range(n)]

Мы также пытались создать массив итеративно, используя циклы, но безуспешно. Я также попробовал это:

y = []
for i in range(0,n):
    y.append([[]*n for i in range(n)])

Есть ли более простой или более интуитивный способ сделать это?

Использование NumPy для многомерных массивов / списков может сэкономить массу головной боли. ninMonkey

Ваш Ответ

10   ответов
1

Я поражен, что никто не пытался придумать общий способ сделать это. Смотрите мой ответ здесь:https://stackoverflow.com/a/33460217/5256940

import copy

def ndlist(init, *args):  # python 2 doesn't have kwarg after *args
    dp = init
    for x in reversed(args):
        dp = [copy.deepcopy(dp) for _ in xrange(x)] # Python 2 xrange
    return dp

l = ndlist(0, 1, 2, 3, 4) # 4 dimensional list initialized with 0's
l[0][1][2][3] = 1

Редактировать: Построен на user2114402 's ответ: добавлено значение по умолчанию

def ndlist(s, v):
    return [ndlist(s[1:], v) for i in xrange(s[0])] if s else v
Возможно. Я'Вы удалили мой комментарий, так как он больше не применяется ... :) DavidW
Меня интересует еще более общий ответ на этот вопрос. Представьте, что у нас N измерений, и нам нужно как получить, так и установить элемент. Получение элемента будет относительно простой рекурсией, в то время как установить элемент не так просто (поправьте меня, если я ошибаюсь). "л [1] [1] [1]» победил'не работает просто потому, что мы незаранее знать количество измерений. Vladimir
я не уверен, что SO должен обрабатывать перекрестные ссылки более разумно :) pterodragon
упс ... пропустил это: D. Я первоначально отправил ответ на другой вопрос, и я скопировал это здесь. Upvoted user2114402 's для короткого рекурсивного ответа. pterodragon
16

Я думаю, что ваши версии понимания списка были очень близки к работе. Ты нене нужно делать какое-либо умножение списка (который неработать с пустыми списками в любом случае). Вот'рабочая версия:

>>> y = [[[] for i in range(n)] for i in range(n)]
>>> print y
[[[], [], [], []], [[], [], [], []], [[], [], [], []], [[], [], [], []]]
1

Очень простой и элегантный способ это:

a = [([0] * 5) for i in range(5)]
a
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
1

Вот'один, который даст вам N мерной "матрица» заполнены копиями копируемого объекта.

редактировать: Это небольшая модификация птеродрагонаОригинальный ответ, который я предпочитаю user2114402 'менее читаемый ответ. На самом деле, за пределами строки документа единственное отличие от птеродрагонаРешение заключается в том, что я явно использую список размеров измерений, а не передаю их пользователем в качестве аргументов.

import copy

    def instantiate_mdl(dim_maxes, base=0):
        """ Instantiate multi-dimensional list, that is a list of list of list ...

        Arguments:
            dim_maxes (list[int]): a list of dimension sizes, for example 
            [2, 4] represents a matrix (represented by lists) of 2 rows and 
            4 columns.     

            base (object): an optional argument indicating the object copies
            of which will reside at the lowest level in the datastructure.
        Returns:
            base (list[base]): a multi-dimensional list of lists structure,
            which is filled with clones of the base parameter.
        """
        for dim_max in reversed(dim_maxes):
            base = [copy.deepcopy(base) for i in range(dim_max)]
        return base

data = instantiate_mdl([3, 5])
data[0][0] = 99999
data[1][1] = 88888
data[2][4] = 77777

for r in data:
    print(r)

>>> # Output
>>> [99999, 0, 0, 0, 0]
>>> [0, 88888, 0, 0, 0]
>>> [0, 0, 0, 0, 77777]
2

я нашел это:

Matrix = [[0 for x in xrange(5)] for x in xrange(5)]

Теперь вы можете добавить элементы в список:

Matrix[0][0] = 1
Matrix[4][0] = 5

print Matrix[0][0] # prints 1
print Matrix[4][0] # prints 5

отсюда:Как определить двумерный массив в Python

отредактировал мой ответ выше user1505695
array = [][] дает мне синтаксическую ошибку. Blckknght
справедливо. но этот ответ можно легко распространить на 3D, нет? или, может быть, я неправильно понял вопрос. user1505695
Это было мое, до твоих правок. Я'Вы удалили его сейчас, так как ваш ответ, по крайней мере, разумен сейчас. Я думаю это'с технической точки зрения все еще неправильно, так как спрашивающий специально хотелn отn от0 трехмерная структура и вытолько делаетn отn двухмерный Blckknght
2

Как насчет этого:

class MultiDimList(object):
    def __init__(self, shape):
        self.shape = shape
        self.L = self._createMultiDimList(shape)
    def get(self, ind):
        if(len(ind) != len(self.shape)): raise IndexError()
        return self._get(self.L, ind)
    def set(self, ind, val):
        if(len(ind) != len(self.shape)): raise IndexError()
        return self._set(self.L, ind, val)
    def _get(self, L, ind):
        return self._get(L[ind[0]], ind[1:]) if len(ind) > 1 else L[ind[0]]
    def _set(self, L, ind, val):
        if(len(ind) > 1): 
            self._set(L[ind[0]], ind[1:], val) 
        else: 
            L[ind[0]] = val
    def _createMultiDimList(self, shape):
        return [self._createMultiDimList(shape[1:]) if len(shape) > 1 else None for _ in range(shape[0])]
    def __repr__(self):
        return repr(self.L)

Затем вы можете использовать его следующим образом

L = MultiDimList((3,4,5)) # creates a 3x4x5 list
L.set((0,0,0), 1)
L.get((0,0,0))
0

Вот более общий способ сделать это.

def ndlist(shape, dtype=list):
    t = '%s for v%d in xrange(shape[%d])'
    cmd = [t % ('%s', i + 1, i) for i in xrange(len(shape))]
    cmd[-1] = cmd[-1] % str(dtype())
    for i in range(len(cmd) - 1)[::-1]:
        cmd[i] = cmd[i] % ('[' + cmd[i + 1]  + ']')
    return eval('[' + cmd[0] + ']')

list_4d = ndlist((2, 3, 4))
list_3d_int = ndlist((2, 3, 4), dtype=int)

print list_4d
print list_3d_int

Результат:

[[[[], [], [], []], [[], [], [], []], [[], [], [], []]], [[[], [], [], []], [[], [], [], []], [[], [], [], []]]]
[[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]]
1
import copy
dimensions = 2, 3, 4
z = 0
genList = lambda size,value: [copy.deepcopy(value) for i in range(size)]
for i in dimensions: z = genList(i, z)
4

Похоже, самый простой способ выглядит следующим образом:

def create_empty_array_of_shape(shape):
    if shape: return [create_empty_array_of_shape(shape[1:]) for i in xrange(shape[0])]

Это'работа для меня

1

В Python я сделал небольшой фабричный метод для создания списка переменных размеров и переменных размеров для каждого из этих измерений:

def create_n_dimensional_matrix(self, n):
  dimensions = len(n)
  if (dimensions == 1): 
    return [0 for i in range(n[0])]

  if (dimensions == 2): 
    return [[0 for i in range(n[0])] for j in range(n[1])]

  if (dimensions == 3): 
    return [[[0 for i in range(n[0])] for j in range(n[1])] for k in range(n[2])]

  if (dimensions == 4): 
    return [[[[0 for i in range(n[0])] for j in range(n[1])] for k in range(n[2])] for l in range(n[3])]

запустите это так:

print(str(k.create_n_dimensional_matrix([2,3])))
print(str(k.create_n_dimensional_matrix([3,2])))
print(str(k.create_n_dimensional_matrix([1,2,3])))
print(str(k.create_n_dimensional_matrix([3,2,1])))
print(str(k.create_n_dimensional_matrix([2,3,4,5])))
print(str(k.create_n_dimensional_matrix([5,4,3,2])))    

Какие отпечатки:

Двумерные списки (2x3), (3x2)Трехмерные списки (1x2x3), (3x2x1)

Четырехмерные списки (2x3x4x5), (5x4x3x2)

[[0, 0], [0, 0], [0, 0]]

[[0, 0, 0], [0, 0, 0]]

[[[0], [0]], [[0], [0]], [[0], [0]]]

[[[0, 0, 0], [0, 0, 0]]]

[[[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]], [[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]], [[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]], [[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]], [[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]]

[[[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]], [[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]]]

Похожие вопросы