私は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 = []
望ましい結果が得られますが、回避策のように感じます。これを行うためのより簡単な/より短い/よりエレガントな方法はありますか?
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) /
あなたは リスト内包表記 を使うことができます。
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回繰り返し作成します。 1つの要素を変更すると各行の同じ要素が変更されるため、これを使用することはできません。
x[:]
はlist(X)
と同等ですが、名前検索を回避するので、もう少し効率的です。いずれにせよ、それは各行の浅いコピーを作成するので、今すべての要素は独立しています。
すべての要素は同じfoo
オブジェクトですが、foo
が可変の場合、この方法は使用できません。
import copy
[[copy.deepcopy(foo) for x in range(10)] for y in range(10)]
あるいはFoo
sを返すクラス(または関数)foo
を仮定する
[[Foo() for x in range(10)] for y in range(10)]
[[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]は素晴らしいです。
Pythonで2次元配列を初期化するには:
a = [[0 for x in range(columns)] for y in range(rows)]
[[foo for x in xrange(10)] for y in xrange(10)]
通常、多次元配列が必要なときは、リストのリストは必要ありませんが、むしろ派手な配列または場合によっては辞書が必要です。
例えば、でたらめなあなたは次のようなことをするでしょう。
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']]
人口密度の低い配列の場合は、Tupleをキーとする辞書を使用することをお勧めします。
dict = {}
key = (a,b)
dict[key] = value
...
twod_list = [[foo for _ in range(m)] for _ in range(n)]
nは行数、mは列数、fooは値です。
これを作成するために最も単純な考えを使用してください。
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)]
t = [ [0]*10 for i in [0]*10]
要素ごとに新しい[0]*10
が作成されます。
>>> 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
そのため、この方法を使用してデフォルト値を正しく設定してください。
マイクの 二重ループ の回答に従ってください。
これを試すことができます[[0] * 10] * 10。これにより、セルごとに値が0の10行10列の2次元配列が返されます。
Matrix={}
for i in range(0,3):
for j in range(0,3):
Matrix[i,j] = raw_input("Enter the matrix:")
@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])
これは私が新しいプログラマーを教えるために、そして追加のライブラリを使わずに見つけた最高のものです。私はもっと良いものが欲しいのですが。
def initialize_twodlist(value):
list=[]
for row in range(10):
list.append([value]*10)
return list
寸法を追加する一般的なパターンは、このシリーズから引き出すことができます。
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)
私はしばしば2次元配列を初期化するためにこのアプローチを使います
n=[[int(x) for x in input().split()] for i in range(int(input())]
私が理解した重要なことは次のとおりです:配列を初期化するとき(任意の次元で)配列のすべての位置にデフォルト値を与える必要があります。その後、初期化のみが完了します。その後、配列の任意の位置で新しい値を変更または受け取ることができます。以下のコードは私のために完璧に働いた
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)
これがもっと簡単な方法です:
import numpy as np
twoD = np.array([[]*m]*n)
すべてのセルを 'x'値で初期化するには、次のようにします。
twoD = np.array([[x]*m]*n