Как инициализировать двумерный массив в Python?
Я начинаю python и пытаюсь использовать двумерный список, который я изначально заполняю одной и той же переменной в каждом месте. Я придумал вот что:
def initialize_twodlist(foo):
twod_list = []
new = []
for i in range (0, 10):
for j in range (0, 10):
new.append(foo)
twod_list.append(new)
new = []
это дает желаемый результат, но похоже на обходной путь. Есть ли более простой / короткий / более элегантный способ сделать это?
20 ответов:
шаблон, который часто появлялся в Python, был
bar = [] for item in some_iterable: bar.append(SOME EXPRESSION)что помогло мотивировать введение списка понимания, которые преобразуют этот фрагмент в
bar = [SOME EXPRESSION for item in some_iterable]который короче и иногда яснее. Обычно вы привыкаете распознавать их и часто заменяете петли на понимания.
ваш код следует этой схеме дважды
twod_list = [] \ for i in range (0, 10): \ new = [] \ can be replaced } this too for j in range (0, 10): } with a list / new.append(foo) / comprehension / twod_list.append(new) /
вы можете использовать понимание:
x = [[foo for i in range(10)] for j in range(10)] # x is now a 10x10 array of 'foo' (which can depend on i and j if you want)
этот путь быстрее чем вложенный список понимания
[x[:] for x in [[foo] * 10] * 10] # for immutable foo!вот некоторые тайминги python3, для малых и больших списков
$python3 -m timeit '[x[:] for x in [[1] * 10] * 10]' 1000000 loops, best of 3: 1.55 usec per loop $ python3 -m timeit '[[1 for i in range(10)] for j in range(10)]' 100000 loops, best of 3: 6.44 usec per loop $ python3 -m timeit '[x[:] for x in [[1] * 1000] * 1000]' 100 loops, best of 3: 5.5 msec per loop $ python3 -m timeit '[[1 for i in range(1000)] for j in range(1000)]' 10 loops, best of 3: 27 msec per loopобъяснение:
[[foo]*10]*10создает список одного и того же объекта повторяется 10 раз. Вы не можете просто использовать это, потому что изменение одного элемента изменит тот же элемент в каждой строке!
x[:]эквивалентноlist(X)но это немного более эффективным, так как не имя уважать. В любом случае, он создает мелкую копию каждой строки, поэтому теперь все элементы независимы.все элементы одинаковы
fooобъект, хотя, так что еслиfooизменчиво, вы не можете использовать эту схему. вам придется использоватьimport copy [[copy.deepcopy(foo) for x in range(10)] for y in range(10)]или предполагая класс (или функцию)
Fooвозвращаетfoos[[Foo() for x in range(10)] for y in range(10)]
для инициализации двумерного массива в Python:
a = [[0 for x in range(columns)] for y in range(rows)]
Не используйте [[v]*n]*n, это ловушка!
>>> a = [[0]*3]*3 >>> a [[0, 0, 0], [0, 0, 0], [0, 0, 0]] >>> a[0][0]=1 >>> a [[1, 0, 0], [1, 0, 0], [1, 0, 0]]но t = [[0]*3 для i в диапазоне (3)] это здорово
обычно, когда вам нужны многомерные массивы, вам не нужен список списков, а скорее массив numpy или, возможно, dict.
например, с numpy вы бы сделали что-то вроде
import numpy a = numpy.empty((10, 10)) a.fill(foo)
вы можете сделать это:
[[element] * numcols] * numrowsнапример:
>>> [['a'] *3] * 2 [['a', 'a', 'a'], ['a', 'a', 'a']]но это имеет нежелательный побочный эффект:
>>> b = [['a']*3]*3 >>> b [['a', 'a', 'a'], ['a', 'a', 'a'], ['a', 'a', 'a']] >>> b[1][1] 'a' >>> b[1][1] = 'b' >>> b [['a', 'b', 'a'], ['a', 'b', 'a'], ['a', 'b', 'a']]
Если это малонаселенный массив, вам может быть лучше использовать словарь с ключом с кортежем:
dict = {} key = (a,b) dict[key] = value ...
используйте самый простой думаю, чтобы создать это.
wtod_list = []и добавить размер:
wtod_list = [[0 for x in xrange(10))] for x in xrange(10)]или если мы хотим объявить размер во-первых. мы используем только:
wtod_list = [[0 for x in xrange(10))] for x in xrange(10)]
неверный подход: [[None*m]*n]
>>> m, n = map(int, raw_input().split()) 5 5 >>> x[0][0] = 34 >>> x [[34, None, None, None, None], [34, None, None, None, None], [34, None, None, None, None], [34, None, None, None, None], [34, None, None, None, None]] >>> id(x[0][0]) 140416461589776 >>> id(x[3][0]) 140416461589776при таком подходе python не позволяет создавать другое адресное пространство для внешних столбцов и приведет к различным нарушениям, чем вы ожидаете.
правильный подход, но с исключением:
y = [[0 for i in range(m)] for j in range(n)] >>> id(y[0][0]) == id(y[1][0]) Falseэто хороший подход, но есть исключение, если вы установите значение по умолчанию
None>>> r = [[None for i in range(5)] for j in range(5)] >>> r [[None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None]] >>> id(r[0][0]) == id(r[2][0]) Trueпоэтому установите значение по умолчанию правильно, используя это подход.
абсолютно правильное:
следуйте ответу микрофона двойная петля.
как указывали @Arnab и @Mike, массив не является списком. Несколько отличий: 1) массивы имеют фиксированный размер во время инициализации 2) массивы обычно поддерживают меньшие операции, чем список.
возможно, в большинстве случаев это перебор, но вот базовая реализация 2d-массива, которая использует аппаратную реализацию массива с использованием python ctypes (C-библиотеки)
import ctypes class Array: def __init__(self,size,foo): #foo is the initial value self._size = size ArrayType = ctypes.py_object * size self._array = ArrayType() for i in range(size): self._array[i] = foo def __getitem__(self,index): return self._array[index] def __setitem__(self,index,value): self._array[index] = value def __len__(self): return self._size class TwoDArray: def __init__(self,columns,rows,foo): self._2dArray = Array(rows,foo) for i in range(rows): self._2dArray[i] = Array(columns,foo) def numRows(self): return len(self._2dArray) def numCols(self): return len((self._2dArray)[0]) def __getitem__(self,indexTuple): row = indexTuple[0] col = indexTuple[1] assert row >= 0 and row < self.numRows() \ and col >=0 and col < self.numCols(),\ "Array script out of range" return ((self._2dArray)[row])[col] if(__name__ == "__main__"): twodArray = TwoDArray(4,5,5)#sample input print(twodArray[2,3])
twod_list = [[foo for _ in range(m)] for _ in range(n)]для n-количество строк, а m-количество столбцов, а foo-значение.
Это лучшее что я нашел для обучения новых программистов, и без использования дополнительных библиотек. Но мне бы хотелось чего-нибудь получше.
def initialize_twodlist(value): list=[] for row in range(10): list.append([value]*10) return list
вот более простой способ :
import numpy as np twoD = np.array([[]*m]*n)для инициализации всех ячеек с любым значением ' x ' Используйте:
twoD = np.array([[x]*m]*n
часто я использую этот подход для инициализации 2-мерный массив
n=[[int(x) for x in input().split()] for i in range(int(input())]
общий шаблон для добавления размеров может быть нарисован из этой серии:
x = 0 mat1 = [] for i in range(3): mat1.append(x) x+=1 print(mat1) x=0 mat2 = [] for i in range(3): tmp = [] for j in range(4): tmp.append(x) x+=1 mat2.append(tmp) print(mat2) x=0 mat3 = [] for i in range(3): tmp = [] for j in range(4): tmp2 = [] for k in range(5): tmp2.append(x) x+=1 tmp.append(tmp2) mat3.append(tmp) print(mat3)
from random import randint l = [] for i in range(10): k=[] for j in range(10): a= randint(1,100) k.append(a) l.append(k) print(l) print(max(l[2])) b = [] for i in range(10): a = l[i][5] b.append(a) print(min(b))
Comments