Многомерный массив в Python

Когда вы вызываете std::vector::resize(X), вы просите vector (по крайней мере, потенциально) создать X объекты. Единственный способ, которым вектор может это сделать, - это построить их по умолчанию, потому что вы больше ничего не даете ему. А поскольку ваша структура не имеет конструктора по умолчанию, resize не может быть скомпилирован.

И на всякий случай ваша структура не имеет конструктора по умолчанию, потому что вы объявили конструктор пользователя.

8
задан Christian Stade-Schuldt 3 February 2009 в 19:54
поделиться

12 ответов

Можно создать его с помощью вложенных списков:

matrix = [[a,b],[c,d],[e,f]]

Если это должно быть динамично, это более сложно, почему бы не записать маленький класс самостоятельно?

class Matrix(object):
    def __init__(self, rows, columns, default=0):
        self.m = []
        for i in range(rows):
            self.m.append([default for j in range(columns)])

    def __getitem__(self, index):
        return self.m[index]

Это может использоваться как это:

m = Matrix(10,5)
m[3][6] = 7
print m[3][6] // -> 7

Я уверен, что мог реализовать его намного более эффективный.:)

При необходимости в многомерных массивах, можно или создать массив и вычислить смещение, или Вы использовали бы массивы в массивах в массивах, которые могут быть довольно плохими для памяти. (Могло быть быстрее, хотя …), я реализовал первую идею как это:

class Matrix(object):
    def __init__(self, *dims):
        self._shortcuts = [i for i in self._create_shortcuts(dims)]
        self._li = [None] * (self._shortcuts.pop())
        self._shortcuts.reverse()

    def _create_shortcuts(self, dims):
        dimList = list(dims)
        dimList.reverse()
        number = 1
        yield 1
        for i in dimList:
            number *= i
            yield number

    def _flat_index(self, index):
        if len(index) != len(self._shortcuts):
            raise TypeError()

        flatIndex = 0
        for i, num in enumerate(index):
            flatIndex += num * self._shortcuts[i]
        return flatIndex

    def __getitem__(self, index):
        return self._li[self._flat_index(index)]

    def __setitem__(self, index, value):
        self._li[self._flat_index(index)] = value

Может использоваться как это:

m = Matrix(4,5,2,6)
m[2,3,1,3] = 'x'
m[2,3,1,3] // -> 'x'
11
ответ дан 5 December 2019 в 04:28
поделиться

Если Вы ограничиваете себя библиотекой стандарта Python, то список списков является самой близкой конструкцией:

arr = [[1,2],[3,4]]

дает как будто 2-й массив. К строкам можно получить доступ как arr[i] для i в {0,..,len(arr}, но доступ столбца является трудным.

Если Вы готовы добавить зависимость библиотеки, пакет NumPy - то, что Вы действительно хотите. Можно создать массив фиксированной длины из списка использования списков:

import numpy
arr = numpy.array([[1,2],[3,4]])

Доступ столбца совпадает с для списка списков, но доступ столбца легок: arr[:,i] для i в {0,..,arr.shape[1]} (число столбцов).

На самом деле массивы NumPy могут быть n-мерными.

Пустые массивы могут быть созданы с

numpy.empty(shape)

где shape кортеж размера в каждом размере; shape=(1,3,2) дает 3-й массив с размером 1 в первом размере, размер 3 во втором размере и 2 в 3-м размере.

Если Вы хотите хранить объекты в массиве NumPy, можно сделать это также:

 arr = numpy.empty((1,), dtype=numpy.object)
 arr[0] = 'abc'

Для большего количества информации о проекте NumPy проверьте домашнюю страницу NumPy.

18
ответ дан 5 December 2019 в 04:28
поделиться

Создать стандартный массив Python массивов произвольного размера:

a = [[0]*cols for _ in [0]*rows]

К этому получают доступ как это:

a[0][1] = 5 # set cell at row 0, col 1 to 5

Маленький глюк Python это стоит упомянуть: заманчиво просто ввести

a = [[0]*cols]*rows

но это скопирует тот же массив столбца в каждую строку, приводящую к нежелательному поведению. А именно:

>>> a[0][0] = 5
>>> print a[1][0]
5
13
ответ дан 5 December 2019 в 04:28
поделиться

Многомерные массивы немного темны. Существует немного причин использования их и многих причин размышления дважды и использования чего-то еще, что более правильно отражает то, что Вы делаете. [Подсказка. Ваш вопрос был тонким на контексте ;-)]

При выполнении матричной математики то используйте numpy.

Однако некоторые люди работали с языками, которые вынуждают их использовать многомерные массивы, потому что это - все, что они имеют. Если Ваш столь же старый, как я (я начал программировать в 70-х) затем можно помнить дни, когда многомерные массивы были единственной структурой данных, Вы имели. Или, Ваш опыт, возможно, ограничил Вас языками, где необходимо было превратить проблему в многомерные массивы.

Скажите, что у Вас есть набор n 3D точки. Каждая точка имеет x, y, z, и временную стоимость. Действительно ли это - массив n x 4? Или 4 * n массив?Не совсем.

Так как каждая точка имеет 4 фиксированных значения, это - более правильно список кортежей.

a = [ ( x, y, z, t ), ( x, y, z, t ), ... ]

Лучше все еще мы могли представить это как список объектов.

class Point( object ):
    def __init__( self, x, y, z, t ):
        self.x, self.y, self.z, self.t = x, y, z, t

a = [ Point(x,y,x,t), Point(x,y,z,t), ... ]
10
ответ дан 5 December 2019 в 04:28
поделиться

Смотрите на numpy

вот фрагмент кода для Вас

import numpy as npy

d = npy.zeros((len(x)+1, len(y)+1, len(x)+len(y)+3))
d[0][0][0] = 0 # although this is unnecessary since zeros initialises to zero
d[i][j][k] = npy.inf

Я не думаю, что необходимо реализовывать научное приложение для выравнивания по ширине использования numpy. Это быстрее и более гибко, и можно сохранить в значительной степени что-либо. Учитывая, что я думаю, что, вероятно, лучше попытаться выровнять по ширине не использование его. Существуют законные причины, но это добавляет много и стоит очень мало так, это заслуживает рассмотрения.

P.S. Действительно ли Ваши длины массива являются правильными? Это похоже на матрицу довольно специфической формы...

11
ответ дан 5 December 2019 в 04:28
поделиться

Если Вы в порядке с помощью разреженных массивов, Вы могли бы использовать dict для хранения значений. dicts Python позволяют Вам использовать кортежи в качестве ключей, как таковых, Вы могли присвоиться к и элементы доступа "разреженного массива" (который является действительно dict здесь) как это:

d = {}
d[0,2,7] = 123 # assign 123 to x=0, y=2, z=7
v = d[0,2,7]
5
ответ дан 5 December 2019 в 04:28
поделиться

Вероятно, не важный для Вас, но если Вы делаете серьезную матричную работу, см. numpy

4
ответ дан 5 December 2019 в 04:28
поделиться

Другая опция состоит в том, чтобы использовать словарь:

>>> from collections import defaultdict
>>> array = defaultdict(int) # replace int with the default-factory you want
>>> array[(0,0)]
0
>>> array[(99,99)]
0

Необходимо будет отслеживать верхние и нижние границы также.

0
ответ дан 5 December 2019 в 04:28
поделиться

Вот быстрый способ создать вложенный 3-мерный список, инициализированный с нулями:

# dim1, dim2, dim3 are the dimensions of the array
a =[[[0 for _ in range(dim1)] for _ in range(dim2)] for _ in range(dim1) ]
a[0][0][0] = 1

это - список списков списков, немного более гибких, чем массив, можно сделать:

a[0][0] = [1,2,3,4]

заменить целую строку в массиве или даже злоупотребить им как этот:

a[0] = "Ouch"
print a[0][0] #will print "O", since strings are indexable the same way as lists
print a[0][0][0] #will raise an error, since "O" isn't indexable

но если Вам нужна производительность, затем я соглашаюсь, что numpy является способом пойти.

Кроме того, остерегайтесь:

a = [[[0] * 5]*5]*5]

Если Вы пробуете a[0][0][0]=7 на объекте выше, Вы будете видеть что случилось с этим.

2
ответ дан 5 December 2019 в 04:28
поделиться

Для числовых данных, Массивов Numpy:

>>> matrix1 = array(([0,1],[1,3]))
>>> print matrix1
[[0 1]
[1 3]]

Для общих данных (например, строки), можно использовать список списков, списка кортежей...

matrix2 = [['a','b'], ['x','y']]
3
ответ дан 5 December 2019 в 04:28
поделиться

Я только что столкнулся с аналогичной потребностью и написал это:

def nDimensionsMatrix(dims, elem_count, ptr=[]):
    if (dims > 1):
        for i in range(elem_count[dims-1]):
            empty = []
            ptr.append(empty)
            nDimensionsMatrix(dims-1, elem_count, empty)
        return ptr
    elif dims == 1:
        ptr.extend([0 for i in range(elem_count[dims])])
        return ptr

matrix = nDimensionsMatrix(3, (2,2,2))

Я не смотрю на скорость, а только на функциональность;)

Я хочу создать матрицу с N измерениями и инициализировать с помощью 0 ( elem_count количество элементов в каждом измерении).

Надеюсь, это поможет кому-то

0
ответ дан 5 December 2019 в 04:28
поделиться

Легко, при использовании numpy:

b = ones((2,3,4)) # creates a 2x3x4 array containing all ones.

«единицы» можно заменить на «нули»

0
ответ дан 5 December 2019 в 04:28
поделиться
Другие вопросы по тегам:

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