web-dev-qa-db-ja.com

Pythonで2次元配列を初期化する方法

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

望ましい結果が得られますが、回避策のように感じます。これを行うためのより簡単な/より短い/よりエレガントな方法はありますか?

223

Pythonでよく登場したパターンは

bar = []
for item in some_iterable:
    bar.append(SOME EXPRESSION)

これは、リスト内包表記の導入を動機付けるのに役立ちました。

bar = [SOME EXPRESSION for item in some_iterable]

これはより短く、時にはより明確です。通常、これらを認識して、しばしばループを内包表記に置き換える習慣があります。

あなたのコードはこのパターンに2回従います

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)                           /
341
Mike Graham

あなたは リスト内包表記 を使うことができます。

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)
183
Adam Rosenfield

この方法は入れ子になったリスト内包表記よりも高速です

[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回繰り返し作成します。 1つの要素を変更すると各行の同じ要素が変更されるため、これを使用することはできません。

x[:]list(X)と同等ですが、名前検索を回避するので、もう少し効率的です。いずれにせよ、それは各行の浅いコピーを作成するので、今すべての要素は独立しています。

すべての要素は同じfooオブジェクトですが、fooが可変の場合、この方法は使用できません。

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

あるいはFoosを返すクラス(または関数)fooを仮定する

[[Foo() for x in range(10)] for y in range(10)]
123
John La Rooy

[[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の範囲(3)のi]は素晴らしいです。

74
Jason CHAN

Pythonで2次元配列を初期化するには:

a = [[0 for x in range(columns)] for y in range(rows)]
51
Vipul
[[foo for x in xrange(10)] for y in xrange(10)]

通常、多次元配列が必要なときは、リストのリストは必要ありませんが、むしろ派手な配列または場合によっては辞書が必要です。

例えば、でたらめなあなたは次のようなことをするでしょう。

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

あなたはこれをすることができます:

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

人口密度の低い配列の場合は、Tupleをキーとする辞書を使用することをお勧めします。

dict = {}
key = (a,b)
dict[key] = value
...
8
btk
twod_list = [[foo for _ in range(m)] for _ in range(n)]

nは行数、mは列数、fooは値です。

4
Moustafa Saleh

これを作成するために最も単純な考えを使用してください。

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)]
3
indi60
t = [ [0]*10 for i in [0]*10]

要素ごとに新しい[0]*10が作成されます。

3
user9269722

間違ったアプローチ:[[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

そのため、この方法を使用してデフォルト値を正しく設定してください。

絶対的に正しい:

マイクの 二重ループ の回答に従ってください。

3
patilnitin

これを試すことができます[[0] * 10] * 10。これにより、セルごとに値が0の10行10列の2次元配列が返されます。

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

@Arnabと@Mikeが指摘したように、配列はリストではありません。違いはほとんどありません。1)初期化中の配列のサイズは固定されています。2)配列は通常、リストより少ない操作をサポートします。

たいていの場合はやり過ぎかもしれませんが、これはpython ctypes(cライブラリ)を使ったハードウェア配列実装を利用する基本的な2次元配列実装です。

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(__== "__main__"):
    twodArray = TwoDArray(4,5,5)#sample input
    print(twodArray[2,3])
1
Antony Thomas

これは私が新しいプログラマーを教えるために、そして追加のライブラリを使わずに見つけた最高のものです。私はもっ​​と良いものが欲しいのですが。

def initialize_twodlist(value):
    list=[]
    for row in range(10):
        list.append([value]*10)
    return list
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)
0
juanfal

私はしばしば2次元配列を初期化するためにこのアプローチを使います

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

0
user6025787

私が理解した重要なことは次のとおりです:配列を初期化するとき(任意の次元で)配列のすべての位置にデフォルト値を与える必要があります。その後、初期化のみが完了します。その後、配列の任意の位置で新しい値を変更または受け取ることができます。以下のコードは私のために完璧に働いた

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)

0
Fairoos Ok

これがもっと簡単な方法です:

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

すべてのセルを 'x'値で初期化するには、次のようにします。

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