Как инициализировать двумерный массив в 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 = []


это дает желаемый результат, но похоже на обходной путь. Есть ли более простой / короткий / более элегантный способ сделать это?

1032   20  

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)] это здорово

[[foo for x in xrange(10)] for y in xrange(10)]

обычно, когда вам нужны многомерные массивы, вам не нужен список списков, а скорее массив 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

поэтому установите значение по умолчанию правильно, используя это подход.

абсолютно правильное:

следуйте ответу микрофона двойная петля.

t = [ [0]*10 for i in [0]*10]

для каждого элемента [0]*10 будет создан ..

как указывали @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])
Matrix={}
for i in range(0,3):
  for j in range(0,3):
    Matrix[i,j] = raw_input("Enter the matrix:")
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

    Ничего не найдено.