Bagaimana cara menginisialisasi array dua dimensi dengan Python?

262

Saya mulai python dan saya mencoba menggunakan daftar dua dimensi, yang awalnya saya isi dengan variabel yang sama di setiap tempat. Saya datang dengan ini:

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

Ini memberikan hasil yang diinginkan, tetapi terasa seperti solusi. Apakah ada cara yang lebih mudah / lebih pendek / lebih elegan untuk melakukan ini?

wajah wajahku
sumber
7
Nitpick kecil (atau signifikan, tergantung pada siapa yang menonton): daftar bukan array. Jika Anda ingin array, gunakan numpy.
Arnab Datta
Pertanyaan ini serupa : membahas inisialisasi array multidimensi dengan Python.
Anderson Green
@ArnabDatta Bagaimana Anda menginisialisasi array multidimensi di numpy, kalau begitu?
Anderson Green
1
@AndersonGreen docs.scipy.org/doc/numpy/user/...
Arnab Datta
Anda dapat mengatur data dalam array seperti struktur dalam Python default tetapi itu tidak seefisien atau berguna sebagai array NumPy. Terutama jika Anda ingin berurusan dengan kumpulan data besar. Berikut ini beberapa dokumentasi docs.scipy.org/doc/numpy-1.10.1/user/basics.creation.html
jmdeamer

Jawaban:

376

Pola yang sering muncul dalam Python adalah

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

yang membantu memotivasi pengenalan daftar, yang mengubah cuplikan itu menjadi

bar = [SOME EXPRESSION for item in some_iterable]

yang lebih pendek dan terkadang lebih jelas. Biasanya Anda terbiasa mengenali ini dan sering mengganti loop dengan pemahaman.

Kode Anda mengikuti pola ini dua kali

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)                           /
Mike Graham
sumber
35
Omong-omong, [[foo] * 10 untuk x in xrange (10)] dapat digunakan untuk menyingkirkan satu pemahaman. Masalahnya adalah bahwa perkalian melakukan salinan dangkal, sehingga baru = [foo] * 10 baru = [baru] * 10 akan membuat Anda daftar yang berisi daftar yang sama sepuluh kali.
Scott Wolchok
8
Demikian pula, [foo] * 10adalah daftar dengan jumlah persis sama foo10 kali, yang mungkin atau mungkin tidak penting.
Mike Graham
2
kita dapat menggunakan hal paling sederhana: wtod_list = [[0 untuk x in xrange (10))] untuk x in xrange (10)]
indi60
2
Tidak ada salahnya untuk menunjukkan kepada seseorang seperti apa rupa ikan itu.
Csteele5
2
Untuk komentar Mike Graham tentang [foo] * 10: Ini berarti bahwa ini tidak akan bekerja jika Anda mengisi array dengan nomor acak (mengevaluasi [random.randint(1,2)] * 10ke [1] * 10atau [2] * 10yang berarti bahwa Anda mendapatkan array dari semua 1s atau 2s, bukan array acak.
Tzu Li
225

Anda dapat menggunakan pemahaman daftar :

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)
Adam Rosenfield
sumber
1
karena ukuran (10) sama dengan baik-baik saja, jika bukan loop bersarang harus didahulukan [foo for j dalam range (range_of_j)] untuk i dalam range (range_of_i)]
Dineshkumar
2
Jawaban ini berfungsi dengan baik, tetapi saya karena kami beralih iuntuk baris dan jkolom, saya pikir itu harus lebih baik untuk bertukar idan jdalam sintaks Anda untuk pemahaman yang lebih baik dan mengubah rentang menjadi 2 angka yang berbeda.
DragonKnight
139

Jangan gunakan [[v]*n]*n, itu jebakan!

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

tapi

    t = [ [0]*3 for i in range(3)]

bekerja dengan baik.

Jason CHAN
sumber
26
ya, saya jatuh ke dalam perangkap ini juga. Itu karena *menyalin addressobjek (daftar).
chinuy
1
Terpilih, karena ini membuat saya. Agar lebih jelas [[0] * col for _ in range(row)],.
Abhijit Sarkar
138

Cara ini lebih cepat daripada pemahaman daftar bersarang

[x[:] for x in [[foo] * 10] * 10]    # for immutable foo!

Berikut adalah beberapa timing python3, untuk daftar kecil dan besar

$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

Penjelasan:

[[foo]*10]*10membuat daftar objek yang sama diulang 10 kali. Anda tidak bisa hanya menggunakan ini, karena memodifikasi satu elemen akan mengubah elemen yang sama di setiap baris!

x[:]setara dengan list(X)tetapi sedikit lebih efisien karena menghindari pencarian nama. Either way, itu membuat salinan dangkal setiap baris, jadi sekarang semua elemen independen.

Semua elemen adalah fooobjek yang sama , jadi jika foobisa berubah , Anda tidak dapat menggunakan skema ini., Anda harus menggunakannya

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

atau dengan asumsi kelas (atau fungsi) Fooyang mengembalikan foos

[[Foo() for x in range(10)] for y in range(10)]
John La Rooy
sumber
4
@ Mike, apakah Anda melewatkan bagian dalam huruf tebal? jika foo bisa berubah, tidak ada jawaban lain di sini yang berfungsi (kecuali Anda tidak mengubah foo sama sekali)
John La Rooy
1
Anda tidak dapat menyalin objek sewenang-wenang dengan benar copy.deepcopy. Anda memerlukan paket khusus untuk data Anda jika Anda memiliki objek yang bisa berubah-ubah.
Mike Graham
1
Jika Anda membutuhkan kecepatan yang sangat buruk dalam satu lingkaran, mungkin ini saatnya menggunakan Cython, menenun, atau yang serupa ...
james.haggerty
1
@ JohnLaRooy saya pikir Anda bertukar xdan y. Bukankah seharusnya[[copy.deepcopy(foo) for y in range(10)] for x in range(10)]
user3085931
1
@Nils [foo]*10tidak membuat 10 objek berbeda - tetapi mudah untuk mengabaikan perbedaan dalam kasus di mana foo tidak dapat diubah, seperti sebuah intatau str.
John La Rooy
62

Untuk menginisialisasi array dua dimensi dengan Python:

a = [[0 for x in range(columns)] for y in range(rows)]
Vipul
sumber
4
Untuk menginisialisasi semua nilai ke 0, cukup gunakan 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)]
Ignacio Vazquez-Abrams
sumber
1
xrange () telah dihapus dalam python3.5
MiaeKim
mengapa ini tidak berhasil: [0 * col] * baris. Ketika saya memodifikasi beberapa elemen itu mereplikasi di tempat lain. Tapi saya tidak mengerti kenapa?
code muncher
Karena itu melakukan hal yang persis sama dengan kode dalam pertanyaan.
Ignacio Vazquez-Abrams
2
@codemuncher Alasan yang [[0] * col] * rowtidak melakukan apa yang Anda inginkan adalah karena ketika Anda menginisialisasi daftar 2d dengan cara itu, Python tidak akan membuat salinan berbeda dari setiap baris. Sebaliknya itu akan init daftar luar dengan pointer ke salinan yang sama [0]*col. Hasil edit apa pun yang Anda buat pada salah satu baris akan tercermin dalam baris yang tersisa karena semuanya sebenarnya menunjuk ke data yang sama dalam memori.
Addie
Hanya pemikiran tetapi tidak semua daftar ini tidak baik untuk ditambahkan? Yaitu. jika saya ingin daftar 2D kosong dimensi 3 * 6 dan ingin menambahkan indeks [0] [0], [1] [0], [2] [0] dan seterusnya untuk mengisi semua 18 elemen, tidak ada jawaban ini akan berhasil bukan?
mLstudent33
22

Biasanya ketika Anda ingin array multidimensi Anda tidak ingin daftar daftar, melainkan array numpy atau mungkin dict.

Misalnya, dengan numpy Anda akan melakukan sesuatu seperti

import numpy
a = numpy.empty((10, 10))
a.fill(foo)
Mike Graham
sumber
2
Meskipun numpyhebat, saya pikir itu mungkin sedikit berlebihan bagi seorang pemula.
Esteban Küber
3
numpy menyediakan tipe array multidimensi. Membangun array multidimensi yang baik dari daftar dimungkinkan tetapi kurang bermanfaat dan lebih sulit bagi pemula daripada menggunakan numpy. Daftar bersarang sangat bagus untuk beberapa aplikasi, tetapi biasanya bukan yang diinginkan oleh seseorang yang menginginkan array 2d.
Mike Graham
1
setelah beberapa tahun sesekali melakukan aplikasi python yang serius, quirks dari standar python array tampaknya hanya akan berjalan terus numpy. +1
javadba
12

Anda dapat melakukan ini:

[[element] * numcols] * numrows

Sebagai contoh:

>>> [['a'] *3] * 2
[['a', 'a', 'a'], ['a', 'a', 'a']]

Tetapi ini memiliki efek samping yang tidak diinginkan:

>>> 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']]
sampai sekarang
sumber
11
Dalam pengalaman saya, efek "tidak diinginkan" ini sering menjadi sumber dari beberapa kesalahan logis yang sangat buruk. Menurut pendapat saya, pendekatan ini harus dihindari, bukan jawaban @ vipul jauh lebih baik.
Alan Turing
pendekatan ini bekerja dengan baik, mengapa dalam komentar beberapa orang menyebutnya buruk?
Bravo
1
Karena efek samping yang kurang diinginkan, Anda tidak dapat benar-benar memperlakukannya sebagai sebuah matriks. Jika Anda tidak perlu mengubah isinya maka tidak apa-apa.
sampai
9
twod_list = [[foo for _ in range(m)] for _ in range(n)]

untuk n adalah jumlah baris, dan m adalah jumlah kolom, dan foo adalah nilainya.

Moustafa Saleh
sumber
8

Jika array ini jarang diisi, Anda mungkin lebih baik menggunakan kamus yang dikunci dengan tuple:

dict = {}
key = (a,b)
dict[key] = value
...
btk
sumber
5
t = [ [0]*10 for i in [0]*10]

untuk setiap elemen baru [0]*10akan dibuat ..

pengguna9269722
sumber
4

Pendekatan Salah: [[Tidak Ada * 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

Dengan pendekatan ini, python tidak mengizinkan pembuatan ruang alamat yang berbeda untuk kolom luar dan akan menyebabkan berbagai kesalahan perilaku daripada yang Anda harapkan.

Pendekatan yang Benar tetapi dengan pengecualian:

y = [[0 for i in range(m)] for j in range(n)]
>>> id(y[0][0]) == id(y[1][0])
False

Ini adalah pendekatan yang baik tetapi ada pengecualian jika Anda menetapkan nilai default 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

Jadi atur nilai default Anda dengan benar menggunakan pendekatan ini.

Benar sekali:

Ikuti balasan mike dari loop ganda .

patilnitin
sumber
3
Matrix={}
for i in range(0,3):
  for j in range(0,3):
    Matrix[i,j] = raw_input("Enter the matrix:")
Sparsh
sumber
1
Sementara kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang mengapa dan / atau bagaimana kode ini menjawab pertanyaan meningkatkan nilai jangka panjangnya.
Ajean
3

Untuk menginisialisasi penggunaan array 2 dimensi: arr = [[]*m for i in range(n)]

sebenarnya, arr = [[]*m]*nakan membuat array 2D di mana semua n array akan menunjuk ke array yang sama, sehingga setiap perubahan nilai dalam elemen apa pun akan tercermin di semua daftar n

untuk penjelasan lebih lanjut, kunjungi: https://www.geeksforgeeks.org/python-using-2d-arrays-lists-the-right-way/

Abimanyu
sumber
3

gunakan pemikiran paling sederhana untuk membuat ini.

wtod_list = []

dan tambahkan ukuran:

wtod_list = [[0 for x in xrange(10)] for x in xrange(10)]

atau jika kita ingin mendeklarasikan ukurannya terlebih dahulu. kami hanya menggunakan:

   wtod_list = [[0 for x in xrange(10)] for x in xrange(10)]
indi60
sumber
1

Seperti yang ditunjukkan oleh @Arnab dan @Mike, array bukanlah daftar. Beberapa perbedaan adalah 1) array ukuran tetap selama inisialisasi 2) array biasanya mendukung operasi yang lebih rendah daripada daftar.

Mungkin berlebihan dalam banyak kasus, tapi di sini adalah implementasi array 2d dasar yang memanfaatkan implementasi array perangkat keras menggunakan python ctypes (c libraries)

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])
Antony Thomas
sumber
1

Yang penting saya mengerti adalah: Ketika menginisialisasi array (dalam dimensi apa pun), kita harus memberikan nilai default untuk semua posisi array. Maka hanya inisialisasi yang selesai. Setelah itu, kami dapat mengubah atau menerima nilai baru ke posisi array apa pun. Kode di bawah ini berfungsi dengan baik untuk saya

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)
Fairoos Ok
sumber
1

Jika Anda menggunakan numpy , Anda dapat dengan mudah membuat array 2d:

import numpy as np

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

x

array([[10, 10, 10, 10, 10],
       [10, 10, 10, 10, 10],
       [10, 10, 10, 10, 10]])
Mehmet Emin Yıldırım
sumber
1
row=5
col=5
[[x]*col for x in [b for b in range(row)]]

Di atas akan memberi Anda array 2D 5x5

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

Ini menggunakan pemahaman daftar bersarang. Breakdown seperti di bawah ini:

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

[x] * col -> ekspresi akhir yang dievaluasi
untuk x in -> x akan menjadi nilai yang diberikan oleh iterator
[b untuk b dalam rentang (baris)]] -> Iterator.

[b untuk b dalam rentang (baris)]] ini akan dievaluasi menjadi [0,1,2,3,4] karena baris = 5
jadi sekarang ia disederhanakan menjadi

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

Ini akan mengevaluasi ke [[0] * 5 untuk x di [0,1,2,3,4]] -> dengan x = 0 iterasi pertama
[[1] * 5 untuk x di [0,1,2, 3,4]] -> dengan x = 1 iterasi ke 2
[[2] * 5 untuk x di [0,1,2,3,4]] -> dengan x = 2 iterasi ke-3
[[3] * 5 untuk x dalam [0,1,2,3,4]] -> dengan x = 3 iterasi ke 4
[[4] * 5 untuk x dalam [0,1,2,3,4]] -> dengan x = 4 iterasi ke-5

Satya
sumber
0

Ini adalah yang terbaik yang saya temukan untuk mengajar programmer baru, dan tanpa menggunakan perpustakaan tambahan. Saya ingin sesuatu yang lebih baik.

def initialize_twodlist(value):
    list=[]
    for row in range(10):
        list.append([value]*10)
    return list
Paul Vincent Craven
sumber
0

Ini cara yang lebih mudah:

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

Untuk menginisialisasi semua sel dengan menggunakan nilai 'x':

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

Seringkali saya menggunakan pendekatan ini untuk menginisialisasi array 2 dimensi

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


sumber
0

Pola umum untuk menambahkan dimensi dapat diambil dari seri ini:

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)
juanfal
sumber
Selamat datang di SO. Pertanyaan ini sudah memiliki jawaban yang diterima secara besar-besaran. Pada pandangan pertama, postingan ini sebenarnya tidak menjawab pertanyaan. Lihat stackoverflow.com/help/how-to-answer untuk panduan.
Nick
0

Anda dapat mencoba ini [[0] * 10] * 10. Ini akan mengembalikan array 2d dari 10 baris dan 10 kolom dengan nilai 0 untuk setiap sel.

ishant
sumber
Ini pada dasarnya adalah jawaban yang sama seperti stackoverflow.com/a/25601284/2413201 ...
Armali
2
Ini menciptakan array 10 pointer ke baris yang sama. Jika Anda melakukannya a = [[0]*10]*10dan kemudian a[0][0] = 1Anda akan melihat bahwa elemen pertama di setiap baris sekarang sama dengan 1
andnik
0

lst = [[0] * m untuk saya dalam kisaran (n)]

inisialisasi semua matriks n = baris dan m = kolom

HRITIK RAJENDRA AKOLKAR
sumber
Bisakah Anda memformat kode sebagai kode? Itu akan jauh lebih mudah dibaca.
Thomas
0

Cara lain adalah dengan menggunakan kamus untuk memegang array dua dimensi.

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

Ini hanya dapat menampung 1D, nilai 2D dan untuk menginisialisasi ini ke 0atau nilai int lainnya, gunakan koleksi .

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

Kode:

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 harus kekal.

Abhishek Bhatia
sumber
-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))
KANDARP JAYESH SHAH
sumber
4
Harap tambahkan beberapa teks yang menjelaskan apa yang kode Anda lakukan.
whackamadoodle3000
1
Biasanya lebih baik menjelaskan solusi daripada hanya memposting beberapa baris kode anonim. Anda dapat membaca Bagaimana cara menulis jawaban yang baik , dan juga Menjelaskan jawaban sepenuhnya berdasarkan kode .
Massimiliano Kraus