2009-02-03 6 views
8

У меня есть небольшая проблема Java, которую я хочу перевести на Python. Поэтому мне нужен многомерный массив. В Java это выглядит так:Многомерный массив в Python

double dArray[][][] = new double[x.length()+1][y.length()+1][x.length()+y.length()+3]; 
dArray[0][0][0] = 0; 
dArray[0][0][1] = POSITIVE_INFINITY; 

Дополнительные значения будут созданы bei-петлями и записаны в массив.

Как создать экземпляр массива?

PS: Там нет умножения матриц участвуют ...

+0

. Кстати, вы можете получить бесконечность бесконечности в python как' float ('inf') '. Он ведет себя более или менее, как и следовало ожидать, - большинство операций просто дают вам inf, а некоторые дают вам nan. –

+0

(объединенный с более ранним вопросом, сохранил это как мастер как: OP все еще существует, b: вопрос лучше сформулирован и c: чтобы избежать множества некромантов) –

ответ

11

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

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

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

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

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

matrix2 = [['a','b'], ['x','y']] 
+0

Могу ли я инициализировать его заданное число строк и столбцов, как в C? – 2008-11-04 05:54:10

+0

Изменчивые объекты (например, список) могут меняться - поэтому инициализация не всегда актуальна. В numpy массив имеет форму (размеры), которая может быть изменена без изменения данных. – gimel

+1

@ Поппер: Да. zeros ((3,4)) создаст массив нулей 3x4. –

18

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

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

дает 2d-подобный массив. Доступ к строкам можно получить как 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 в третьем измерении.

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

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

Для получения дополнительной информации о проекте NumPy, проверьте NumPy homepage.

+0

Нет необходимости использовать кортеж. 'numpy.empty ([1])' также работает. – jfs

+0

Простой «случайный» генератор чисел: 'noise = lambda: numpy.empty ([1]) [0]' – jfs

+0

Правда, любой итерируемый (список, кортеж и т. Д.) Работает как аргумент измерений. Ваш «случайный» генератор чисел полагается на неинициализированную память, которая является «случайной» и должна * никогда не использоваться как источник случайности для всех матов (например, криптография). –

13

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

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

Доступ к нему, как это:

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

Маленький питон Гоча, что стоит отметить: Заманчиво просто наберите

a = [[0]*cols]*rows 

но скопируем же для каждой строки, что приводит к нежелательному поведению. А именно:

>>> a[0][0] = 5 
>>> print a[1][0] 
5 
+4

Я бы предпочел использовать: '[[0] * cols for _ in xrange (rows)]' – jfs

+0

@ J.F.Sebastian Я тоже тоже. Я только что нашел симметрию, привлекательную во время написания этого. :-) – Deestan

+0

plus1 для получения. – AShelly

10

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

Если вы делаете математическую математику, используйте numpy.

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

Скажите, у вас есть коллекция n 3D точки. Каждая точка имеет значения x, y, z и времени. Это массив n x 4? Или a 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), ... ] 
+1

+1. Я бы упомянул 'namedtuple's – jfs

0

Другим вариантом является использование словаря:

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

Вам нужно следить за верхней & нижних границ, а также.

11

Посмотрите на 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 

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

P.S. Правильно ли длина массива? Это выглядит как довольно своеобразной фасонной матрицы ...

4

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

5

Если вы в порядке, используя разреженные массивы, вы могли бы использовать Dict для хранения вашей значения. dicts Python позволяют использовать кортежи в качестве ключей, таким образом, вы могли бы назначить и получить доступ к элементам «разреженный массив» (который на самом деле ДИКТ здесь), как это:

d = {} 
d[0,2,7] = 123 # assign 123 to x=0, y=2, z=7 
v = d[0,2,7] 
+0

Приятный трюк для хранения многомерного массива. Однако все будет очень беспорядочно, если вы попытаетесь выполнить итерацию по элементам, например, о столбце или строке, или даже получить «размеры». –

+0

Действительно. Если бы я использовал что-то вроде этого, я бы, конечно, инкапсулировал это в класс и вводил методы для доступа к чтению/записи. Переменная экземпляра сохранит размер массива, и методы чтения/записи вернут значение по умолчанию для неназначенных элементов (путем захвата KeyError). – paprika

+0

+1: словарь значительно проще. Итерация по размерам проста, а не беспорядочна. xRange = set ([k [0] для k в d.keys()]), yRange = set ([k [1] для k в d.keys()]) –

2

Вот быстрый способ создания вложенное 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] 

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

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 на объекте выше, вы увидите, что случилось с этим.

0

Я только что вышел в подобной необходимости и кодируются следующим образом:

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)) 

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

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

Надежда его помогает кому-то

0

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

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

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

Смежные вопросы