파이썬에서 2 차원 배열을 초기화하는 방법?


262

나는 파이썬을 시작하고 있으며 2 차원 목록을 사용하려고합니다. 처음에는 모든 곳에서 동일한 변수로 채워집니다. 나는 이것을 생각해 냈다.

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 = []

원하는 결과를 제공하지만 해결 방법처럼 느껴집니다. 이 작업을 더 쉽고 짧고 우아한 방법이 있습니까?


7
작은 것 (또는보고있는 사람에 따라 중요) nitpick : 목록은 배열이 아닙니다. 배열을 원하면 numpy를 사용하십시오.
Arnab Datta

이 질문은 비슷합니다 : 파이썬에서 다차원 배열의 초기화에 대해 설명합니다.
Anderson Green

@ArnabDatta 그렇다면 어떻게 다차원 배열을 numpy로 초기화하겠습니까?
Anderson Green


기본 Python의 구조와 같은 배열로 데이터를 정렬 할 수 있지만 NumPy 배열만큼 효율적이거나 유용하지는 않습니다. 특히 큰 데이터 세트를 처리하려는 경우. 다음은 일부 문서입니다. docs.scipy.org/doc/numpy-1.10.1/user/basics.creation.html
jmdeamer

답변:


376

파이썬에서 자주 등장한 패턴은

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

35
그런데 xrange (10)]의 x에 대한 [[foo] * 10]를 사용하면 하나의 이해력을 제거 할 수 있습니다. 문제는 곱셈이 얕은 카피를 수행하므로 new = [foo] * 10 new = [new] * 10은 동일한 목록을 10 번 포함하는 목록을 가져옵니다.
Scott Wolchok

8
마찬가지로, [foo] * 10정확히 foo10 회 동일한 목록 이 중요하거나 중요하지 않을 수 있습니다.
Mike Graham

2
가장 간단한 것을 사용할 수 있습니다 : wtod_list = [[xrange (10)에서 x의 경우 0) xrange (10)에서 x의 경우]
indi60

2
물고기가 어떻게 생겼는지 보여주는 것은 결코 아프지 않습니다.
Csteele5

2
약 마이크 그레이엄의 코멘트 [foo] * 10:이 것없는 일이 당신이 임의의 숫자 (평가됩니다와 배열 작성하는 경우 있음이 수단 [random.randint(1,2)] * 10에를 [1] * 10하거나 [2] * 10하는 대신 임의의 배열, 모두 1 또는 2 초의 배열을 얻을 수 있다는 것을 의미한다.
손자 리

224

당신은 목록 이해를 사용할 수 있습니다 :

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)

1
크기 (10)는 크기가 동일하기 때문에 중첩 루프가 먼저 나오지 않아야합니다 (범위 (range_of_j)에서 j에 대한 foo는 범위 (range_of_i)에서 i)
Dineshkumar

2
이 답변은 우리 반복 처리 이후 미세하지만 작동 i행과 j열에 대해, 나는 그것이 스왑을 더해야한다고 생각 i하고 j더 나은 이해를위한 당신의 구문과 2 개 개의 다른 숫자의 범위를 변경합니다.
DragonKnight

138

이 방법은 중첩 된 목록 이해보다 빠릅니다.

[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]*1010 회 반복 된 동일한 객체의 목록을 만듭니다. 하나의 요소를 수정하면 각 행에서 동일한 요소가 수정되므로 이것을 사용할 수 없습니다!

x[:]list(X)이름 조회를 피하기 때문에 동등 하지만 조금 더 효율적입니다. 어느 쪽이든, 각 행의 얕은 사본을 작성하므로 이제 모든 요소가 독립적입니다.

모든 요소는 동일한 foo객체이므로 foo변경할 수 있으면 이 체계를 사용할 수 없습니다.

import copy
[[copy.deepcopy(foo) for x in range(10)] for y in range(10)]

또는 s Foo를 반환 하는 클래스 (또는 함수) 를 가정foo

[[Foo() for x in range(10)] for y in range(10)]

4
@ 마이크, 굵게 표시된 부분을 놓치셨습니까? 푸 변경할 경우 (당신이 전혀 foo는 돌연변이하지 않는 한) 다른 답변 아무도 여기에 작동하지
존 라 Rooy

1
를 사용하여 임의의 객체를 올바르게 복사 할 수 없습니다 copy.deepcopy. 임의의 변경 가능한 객체가있는 경우 데이터와 관련된 계획이 필요합니다.
Mike Graham

1
루프에서 심하게 속도를 필요로하는 경우, ... 사이 썬, 직조, 또는 유사한을 사용하는 시간이 될 수 있습니다
james.haggerty

1
내가 생각 @JohnLaRooy 당신은 교환 x하고 y. 해서는 안됨[[copy.deepcopy(foo) for y in range(10)] for x in range(10)]
user3085931

1
@Nils는 [foo]*1010 개 개의 서로 다른 객체를 생성하지 않습니다 -하지만 foo는이 같은 불변이고이 경우의 차이를 간과하기 쉽습니다 intstr.
John La Rooy

137

사용하지 마십시오 [[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 for i in range(3)]

잘 작동합니다.


26
예, 나도이 함정에 빠졌습니다. 객체 (목록)를 *복사 하기 때문 입니다 address.
chinuy

1
이것이 나를 얻었 기 때문에 공감되었습니다. 더 명확하게하기 위해 [[0] * col for _ in range(row)].
Abhijit Sarkar

62

파이썬에서 2 차원 배열을 초기화하려면 :

a = [[0 for x in range(columns)] for y in range(rows)]

4
모든 값을 0으로 초기화하려면을 사용하십시오 a = [[0 for x in range(columns)] for y in range(rows)].
ZX9

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

1
xrange ()은 python3.5에서 제거되었습니다
MiaeKim

이것이 작동하지 않는 이유 : [0 * col] * 행. 일부 요소를 수정하면 다른 위치에서 복제됩니다. 그러나 나는 왜 그런지 이해하지 못합니까?
code muncher

그것은 질문의 코드와 정확히 같은 일을하기 때문입니다.
Ignacio Vazquez-Abrams

2
@codemuncher [[0] * col] * row원하는 것을 하지 않는 이유 는 2D 목록을 그런 식으로 초기화 할 때 파이썬이 각 행의 별개의 사본을 만들지 않기 때문입니다. 대신 동일한의 사본에 대한 포인터로 외부 목록을 초기화합니다 [0]*col. 행 중 하나에 대한 편집 내용은 모두 실제로 메모리의 동일한 데이터를 가리 키기 때문에 나머지 행에 반영됩니다.
Addie

그냥 생각하지만이 모든 목록에 추가하기에 좋지 않은가요? 즉. 3 차원 * 6의 빈 2D 목록을 원하고 index [0] [0], [1] [0], [2] [0] 등에 추가하여 18 개 요소를 모두 채우려면 이 답변은 제대로 작동합니까?
mLstudent33 오전

22

일반적으로 다차원 배열을 원할 때 목록 목록이 아니라 numpy 배열 또는 dict이 필요합니다.

예를 들어, numpy를 사용하면 다음과 같은 작업을 수행합니다

import numpy
a = numpy.empty((10, 10))
a.fill(foo)

2
numpy훌륭 하지만 초보자에게는 약간의 과잉 일 수 있다고 생각합니다.
Esteban Küber

3
numpy는 다차원 배열 유형을 제공합니다. 좋은 다차원 배열을 목록으로 만드는 것은 가능하지만 초보자에게는 numpy를 사용하는 것보다 유용하지 않고 어렵습니다. 중첩 된 목록은 일부 응용 프로그램에는 유용하지만 일반적으로 2D 배열을 원하는 사람이 가장 적합한 것은 아닙니다.
Mike Graham

1
몇 년 동안 심각한 파이썬 응용 프로그램을 수행 한 후 표준 파이썬 배열의 단점은 계속 진행할 것입니다 numpy. +1
javadba

12

당신은 이것을 할 수 있습니다 :

[[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']]

11
내 경험상이 "바람직하지 않은"효과는 종종 매우 나쁜 논리적 오류의 원인입니다. 내 의견으로는이 접근법은 피해야하며 @Vipul의 대답이 훨씬 좋습니다.
Alan Turing

이 접근법은 잘 작동합니다. 왜 사람들은 일부 사람들이 그것이 나쁜 것이라고 말합니다.
Bravo

1
바람직하지 않은 부작용으로 인해 실제로이를 매트릭스로 취급 할 수 없습니다. 내용을 변경할 필요가 없으면 괜찮습니다.
hithwen

9
twod_list = [[foo for _ in range(m)] for _ in range(n)]

n은 행 수이고 m은 열 수이며 foo는 값입니다.


8

드물게 인구가 많은 배열 인 경우 튜플이있는 사전을 사용하는 것이 좋습니다.

dict = {}
key = (a,b)
dict[key] = value
...

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

각 요소마다 새로운 [0]*10것이 만들어 질 것입니다 ..


4

잘못된 접근 방식 : [[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

이 방법을 사용하면 파이썬은 외부 열에 대해 다른 주소 공간을 만들 수 없으므로 예상보다 다양한 오작동을 일으킬 수 있습니다.

올바른 접근 방식이지만 예외는 다음과 같습니다.

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

따라서이 방법을 사용하여 기본값을 올바르게 설정하십시오.

절대 맞습니다 :

마이크의 이중 루프 답장을 따르십시오 .


3
Matrix={}
for i in range(0,3):
  for j in range(0,3):
    Matrix[i,j] = raw_input("Enter the matrix:")

1
이 코드는 질문에 대답 할 수 있지만,이 코드가 질문에 응답하는 이유 및 / 또는 방법에 대한 추가 컨텍스트를 제공하면 장기적인 가치가 향상됩니다.
Ajean


3

이것을 만들려면 가장 간단한 생각을 사용하십시오.

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

1

@Arnab과 @Mike가 지적했듯이 배열은 목록이 아닙니다. 몇 가지 차이점은 1) 초기화 중에 배열의 크기가 고정 된 것입니다. 2) 배열은 일반적으로 목록보다 적은 연산을 지원합니다.

아마도 대부분의 경우 과잉 일 수도 있지만 여기에는 파이썬 ctypes (c 라이브러리)를 사용하여 하드웨어 배열 구현을 활용하는 기본 2d 배열 구현이 있습니다.

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

1

내가 이해 한 중요한 것은 : 배열을 초기화하는 동안 (어떤 차원에서든) 배열의 모든 위치에 기본값을 지정해야합니다. 그런 다음 초기화 만 완료됩니다. 그런 다음 배열의 임의의 위치로 새 값을 변경하거나 수신 할 수 있습니다. 아래 코드는 완벽하게 작동했습니다.

N=7
F=2

#INITIALIZATION of 7 x 2 array with deafult value as 0
ar=[[0]*F for x in range(N)]

#RECEIVING NEW VALUES TO THE INITIALIZED ARRAY
for i in range(N):
    for j in range(F):
        ar[i][j]=int(input())
print(ar)

1

numpy 를 사용 하면 2D 배열을 쉽게 만들 수 있습니다.

import numpy as np

row = 3
col = 5
num = 10
x = np.full((row, col), num)

엑스

array([[10, 10, 10, 10, 10],
       [10, 10, 10, 10, 10],
       [10, 10, 10, 10, 10]])

1
row=5
col=5
[[x]*col for x in [b for b in range(row)]]

위의 내용은 5x5 2D 배열입니다.

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

중첩 된 목록 이해를 사용하고 있습니다. 아래와 같이 고장 :

[[x]*col for x in [b for b in range(row)]]

[x] * col-> x in->
x에 대해 평가되는 최종 표현식 은 반복자에 의해 제공되는 값입니다
[범위 (행)에서 b의 경우 b]]-> 반복자.

[범위 (행)의 b에 대한 b]]]는 row = 5
이므로 [0,1,2,3,4]로 평가 되므로 이제는

[[x]*col for x in [0,1,2,3,4]]

이것은 [0,1,2,3,4]에서 x에 대해 [[0] * 5로 평가됨]-> x = 0으로 첫 번째 반복
[[1] * 5에 대해 [0,1,2에서 x에 대해] 3,4]]-> x = 1 인 2 번째 반복
[[1,2,3,4]]에서 x의 x에 대한 [[2] * 5]-> x = 2 인 3 번째 반복
[[3] * 5 x의 경우 [0,1,2,3,4]의 x에 대해 x = 3 일 때 4 번 반복
[[4] * 5의 경우 [0,1,2,3,4]의 x에 대해-> x의 경우 = 4 5 번째 반복


0

이것은 새로운 프로그래머를 가르치고 추가 라이브러리를 사용하지 않고 내가 찾은 최고의 것입니다. 그래도 더 좋은 것을 원합니다.

def initialize_twodlist(value):
    list=[]
    for row in range(10):
        list.append([value]*10)
    return list

0

더 쉬운 방법은 다음과 같습니다.

import numpy as np
twoD = np.array([[]*m]*n)

'x'값으로 모든 셀을 초기화하려면 다음을 사용하십시오.

twoD = np.array([[x]*m]*n

0

종종이 방법을 사용하여 2 차원 배열을 초기화합니다.

n=[[int(x) for x in input().split()] for i in range(int(input())]


0

이 시리즈에서 치수를 추가하는 일반적인 패턴을 그릴 수 있습니다.

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)

SO에 오신 것을 환영합니다. 이 질문에는 이미 큰 찬성 투표가 있습니다. 언뜻보기에이 포스트는 실제로 그 질문에 대답하지 않습니다. 지침 은 stackoverflow.com/help/how-to-answer 를 참조하십시오 .
Nick

0

이 [[0] * 10] * 10을 시도 할 수 있습니다. 그러면 각 셀에 대해 값이 0 인 10 개의 행과 10 개의 열로 구성된 2 차원 배열이 반환됩니다.


이것은 본질적으로 stackoverflow.com/a/25601284/2413201 과 같은 대답입니다 .
Armali

2
이것은 같은 행에 10 개의 포인터 배열을 만듭니다. 당신이 경우에 a = [[0]*10]*10다음 a[0][0] = 1당신은 지금 1로 동일 각 행의 첫 번째 요소를 볼 수
andnik

0

범위 (n)의 i에 대한 lst = [[0] * m]

모든 행렬 초기화 n = 행 및 m = 열


코드를 코드로 포맷 할 수 있습니까? 좀 더 읽기 쉬울 것입니다.
토마스

0

다른 방법은 사전을 사용하여 2 차원 배열을 보유하는 것입니다.

twoD = {}
twoD[0,0] = 0
print(twoD[0,0]) # ===> prints 0

이것은 1D, 2D 값을 보유 할 수 있으며 이것을 0int 또는 다른 int 값 으로 초기화 하려면 collections를 사용하십시오 .

import collections
twoD = collections.defaultdict(int)
print(twoD[0,0]) # ==> prints 0
twoD[1,1] = 1
print(twoD[1,1]) # ==> prints 1

0

암호:

num_rows, num_cols = 4, 2
initial_val = 0
matrix = [[initial_val] * num_cols for _ in range(num_rows)]
print(matrix) 
# [[0, 0], [0, 0], [0, 0], [0, 0]]

initial_val 불변이어야합니다.


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

4
코드의 기능을 설명하는 텍스트를 추가하십시오.
whackamadoodle3000 년

1
일반적으로 익명 코드의 일부 행을 게시하는 대신 솔루션을 설명하는 것이 좋습니다. 좋은 답변을 작성하는 방법전체 코드 기반 답변 설명을 읽을 수 있습니다 .
Massimiliano Kraus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.