Python'da iki boyutlu bir dizi nasıl başlatılır?


262

Ben python başlıyorum ve ben başlangıçta her yerde aynı değişken ile doldurmak iki boyutlu bir liste kullanmaya çalışıyorum. Ben bununla geldim:

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

İstenen sonucu verir, ancak bir geçici çözüm gibi hisseder. Bunu yapmanın daha kolay / daha kısa / daha zarif bir yolu var mı?


7
Sadece küçük (veya kimin izlediğine bağlı olarak önemli) nitpick: listeler diziler değildir. Diziler istiyorsanız numpy kullanın.
Arnab Datta

Bu soru benzer : Python'da çok boyutlu dizilerin başlatılmasını tartışıyor.
Anderson Green

@ArnabDatta Çok boyutlu bir diziyi nümerik olarak nasıl başlatırsınız?
Anderson Green


Verileri varsayılan Python'da yapı benzeri bir dizide düzenleyebilirsiniz, ancak NumPy dizisi kadar etkili veya kullanışlı değildir. Özellikle büyük veri kümeleriyle uğraşmak istiyorsanız. İşte docs.scipy.org/doc/numpy-1.10.1/user/basics.creation.html
jmdeamer

Yanıtlar:


376

Python'da sık sık ortaya çıkan bir model

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

bu pasajı şuna dönüştüren liste kavrayışlarının girişini motive etmeye yardımcı oldu.

bar = [SOME EXPRESSION for item in some_iterable]

ki bu daha kısa ve bazen daha net. Genellikle bunları tanıma ve döngüleri kavrayışlarla değiştirme alışkanlığı kazanırsınız.

Kodunuz bu modeli iki kez izler

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
Bu arada, xrange [10] için [10] * 10, bir kavrayıştan kurtulmak için kullanılabilir. Sorun, çarpmanın sığ bir kopya yapmasıdır, bu nedenle new = [foo] * 10 new = [new] * 10 size aynı listeyi on kez içeren bir liste verecektir.
Scott Wolchok

8
Benzer şekilde, önemli olabilecek veya olmayabilecek [foo] * 10aynı tam foo10 kez bir listedir .
Mike Graham

2
en basit şeyi kullanabiliriz: wtod_list = [[0 için x in xrange (10))]] x in xrange (10)] için
indi60

2
Birine balığın nasıl göründüğünü göstermek asla acıtmaz.
Csteele5

2
Hakkında Mike Graham yorumun için [foo] * 10: Bu olmaz eser rastgele sayılar (değerlendirir içeren bir dizi doldurma eğer o bu yollarla [random.randint(1,2)] * 10için [1] * 10ya [2] * 10hangi yerine rastgele bir dizinin, tümü 1 veya 2 sn bir dizi almak anlamına gelir.
Tzu Li

224

Bir liste kavrayışı kullanabilirsiniz :

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) boyutu aynı olduğundan, iç içe döngü ilk önce gelmemelidir [aralıktaki j için foo (range_of_j)] aralıktaki i (range_of_i) için]
Dineshkumar

2
Bu cevap iyi çalışıyor ancak isatırları ve jsütunları yinelediğimiz için , aralığı daha iyi anlamak ve aralığı 2 farklı sayıya değiştirmek için takas etmeniz ive jsözdiziminizde daha iyi olması gerektiğini düşünüyorum .
Ejderha

138

Bu şekilde iç içe liste kavrayışlarından daha hızlıdır

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

Küçük ve büyük listeler için bazı python3 zamanlamaları

$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

Açıklama:

[[foo]*10]*1010 kez tekrarlanan aynı nesnenin bir listesini oluşturur. Bunu sadece kullanamazsınız, çünkü bir öğeyi değiştirmek her öğedeki aynı öğeyi değiştirir!

x[:]eşdeğerdir list(X)ancak ad aramasını önlediğinden biraz daha verimlidir. Her iki durumda da, her satırın sığ bir kopyasını oluşturur, bu yüzden şimdi tüm öğeler bağımsızdır.

Ancak tüm öğeler aynı foonesnedir, bu nedenle foodeğiştirilebilirse bu şemayı kullanamazsınız.

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

veya s Foodöndüren bir sınıf (veya işlev) varsayarsakfoo

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

4
@Mike, cesurca parçayı özledin mi? Eğer foo değişebilirse, buradaki diğer cevapların hiçbiri işe yaramaz (eğer fooyu hiç mutasyona uğratmazsanız)
John La Rooy

1
Tuşunu kullanarak keyfi nesneleri doğru şekilde kopyalayamazsınız copy.deepcopy. İsteğe bağlı değiştirilebilir bir nesneniz varsa verilerinize özgü bir plana ihtiyacınız vardır.
Mike Graham

1
Bir döngüde bu kadar kötü bir hıza ihtiyacınız varsa, Cython, örgü veya benzerlerini kullanma zamanı gelmiş olabilir ...
james.haggerty

1
@ JohnLaRooy Sanırım birbirinin yerine geçirdin xve y. Olmamalı[[copy.deepcopy(foo) for y in range(10)] for x in range(10)]
user3085931

1
@Nils [foo]*1010 farklı nesne yaratmaz - ancak foo'nun değişmez olduğu durumda, intveya gibi farkları gözden kaçırmak kolaydır str.
John La Rooy

137

Kullanma [[v]*n]*n, bu bir tuzak!

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

fakat

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

harika çalışıyor.


26
evet, ben de bu tuzağa düştüm. Bunun nedeni nesnenin (listenin) *kopyalanmasıdır address.
chinuy

1
Bu beni yakaladığından beri oylandı. Daha açık olmak gerekirse [[0] * col for _ in range(row)],.
Abhijit Sarkar

62

Python'da iki boyutlu bir dizi başlatmak için:

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

4
Tüm değerleri 0 olarak başlatmak için sadece tuşunu kullanın 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 içinde kaldırıldı
MiaeKim

neden çalışmıyor: [0 * col] * satır. Bazı öğeleri değiştirdiğimde başka yerlerde çoğaltır. Ama nedenini anlamıyorum?
kod muncher

Çünkü bu sorudaki kodla aynı şeyi yapıyor.
Ignacio Vazquez-Abrams

2
@codemuncher [[0] * col] * row2d listesini bu şekilde başlattığınızda, Python'un her satırın ayrı kopyalarını oluşturmamasıdır. Bunun yerine, aynı listeye işaretçilerle dış listeyi başlatır [0]*col. Satırlardan birinde yaptığınız tüm düzenlemeler, aslında bellekteki aynı verilere işaret ettiği için kalan satırlara yansıtılacaktır.
Addie

Sadece bir düşünce ama tüm bu listeler eklemek için iyi değil mi? Yani. 3 * 6 boyutunda boş bir 2B liste istiyorum ve [0] [0], [1] [0], [2] [0] dizinine eklemek istiyorum, 18 öğenin tümünü doldurmak için bu cevaplar işe yarayacak mı?
mLstudent33

22

Genellikle çok boyutlu diziler istediğinizde bir liste listesi istemezsiniz, daha ziyade numpy bir dizi veya muhtemelen bir dikte istersiniz.

Örneğin, numpy ile şöyle bir şey yaparsınız

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

2
Her ne kadar numpyharika olsa da, yeni başlayanlar için biraz abartılı olabileceğini düşünüyorum.
Esteban Küber

3
numpy çok boyutlu bir dizi türü sağlar. Listelerden iyi bir çok boyutlu dizi oluşturmak mümkündür, ancak yeni başlayanlar için numpy kullanmaktan daha az kullanışlı ve daha zordur. Yuvalanmış listeler bazı uygulamalar için mükemmeldir, ancak genellikle 2d dizisi isteyen birinin en iyi sonucu vermez.
Mike Graham

1
ara sıra ciddi python uygulamaları yaptıktan birkaç yıl sonra standart python dizilerinin tuhaflıkları devam ediyor gibi görünüyor numpy. +1
javadba

12

Sadece bunu yapabilirsiniz:

[[element] * numcols] * numrows

Örneğin:

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

Ancak bunun istenmeyen bir yan etkisi vardır:

>>> 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
Deneyimlerime göre, bu "istenmeyen" etki genellikle bazı çok kötü mantıksal hataların kaynağıdır. Bence bu yaklaşımdan kaçınılmalı, bunun yerine @ Vipul'un cevabı çok daha iyi.
Alan Turing

bu yaklaşım işe yarıyor, neden bazı insanlarda bu kadar kötü olduğunu belirtiyor?
Bravo

1
Yetersiz yan etkisi nedeniyle, bunu gerçekten bir matris olarak ele alamazsınız. İçeriği değiştirmeniz gerekmiyorsa, sorun olmaz.
17'de

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

çünkü n satır sayısı, m sütun sayısı ve foo değerdir.


8

Seyrek nüfuslu bir dizi ise, bir demet ile anahtarlanmış bir sözlük kullanarak daha iyi olabilirsiniz:

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

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

her eleman için yeni bir [0]*10yaratılacak ..


4

Yanlış Yaklaşım: [[Yok * 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

Bu yaklaşımla, python dış sütunlar için farklı adres alanı oluşturmaya izin vermez ve beklentilerinizden farklı hatalı davranışlara yol açar.

Doğru Yaklaşım ancak istisna hariç:

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

İyi bir yaklaşımdır, ancak varsayılan değeri 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

Bu nedenle, bu yaklaşımı kullanarak varsayılan değerinizi doğru şekilde ayarlayın.

Mutlak doğru:

Mike'ın çift ​​döngü yanıtını izleyin .


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

1
Bu kod soruyu cevaplayabilirken, bu kodun soruyu neden ve / veya nasıl cevapladığı konusunda ek bağlam sağlamak uzun vadeli değerini arttırır.
Ajean


3

bunu oluşturmak için en basit düşünceyi kullanın.

wtod_list = []

ve boyutu ekleyin:

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

veya öncelikle boyutu beyan etmek istiyorsak. sadece kullanıyoruz:

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

1

@Arnab ve @Mike'in işaret ettiği gibi, bir dizi liste değildir. Birkaç farklılık 1) diziler başlatma sırasında sabit boyuttadır 2) diziler normalde bir listeden daha az işlemi destekler.

Belki çoğu durumda bir overkill, ama burada python ctypes (c kütüphaneleri) kullanarak donanım dizisi uygulamasını kullanan temel bir 2d dizi uygulaması

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

Anladığım önemli olan şey: Bir diziyi başlatırken (herhangi bir boyutta) dizinin tüm konumlarına varsayılan bir değer vermeliyiz. Sonra sadece başlatma tamamlanır. Bundan sonra, dizinin herhangi bir konumuna yeni değerler değiştirebilir veya alabiliriz. Aşağıdaki kod benim için mükemmel çalıştı

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 kullanırsanız , kolayca 2d diziler oluşturabilirsiniz:

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

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

Yukarıdaki 5x5 2D dizi verecektir

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

Yuvalanmış liste kavrayışı kullanıyor. Arıza aşağıdaki gibi:

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

[x] * col ->
x inç -> x için değerlendirilen son ifade , yineleyici tarafından sağlanan değer olacaktır
[aralık (satır) b için b]] -> Yineleyici.

[b aralığı (satır) için b]]], satır = 5
olduğundan [0,1,2,3,4] olarak değerlendirilir, bu nedenle şimdi

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

Bu, [0,1,2,3,4]] -> x için [[0] * 5 olarak değerlendirilecektir. X = 0 1. yineleme ile
[[1] * 5, [0,1,2, 3,4]] -> x = 1 2. yineleme ile
[[2] * 5, [0,1,2,3,4]] x için -> x = 2 3. yineleme ile
[[3] * 5 [0,1,2,3,4]] içindeki x için -> x = 3 4. yineleme ile
[[4] * 5 için [0,1,2,3,4]] -> ile x = 4 5. yineleme


0

Bu, yeni programcıları öğretmek için ve ek kütüphaneler kullanmadan bulduğum en iyisi. Yine de daha iyi bir şey rica ediyorum.

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

0

İşte daha kolay bir yol:

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

Tüm hücreleri herhangi bir 'x' değeriyle başlatmak için şunu kullanın:

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

0

Genellikle bu yaklaşımı 2 boyutlu bir dizi başlatmak için kullanıyorum

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


0

Boyut eklemek için genel desen bu seriden çizilebilir:

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 hoş geldiniz. Bu soru zaten çok oyla kabul edilmiş bir cevaba sahip. İlk bakışta, bu yazı aslında soruyu cevaplamıyor. Yardım için stackoverflow.com/help/how-to-answer adresine bakın .
Nick

0

Bunu deneyebilirsiniz [[0] * 10] * 10. Bu, her hücre için 0 değerine sahip 10 satır ve 10 sütundan oluşan 2d dizisini döndürür.


Bu aslında stackoverflow.com/a/25601284/2413201 ile aynı cevaptır …
Armali

2
Bu, aynı satıra 10 işaretçi dizisi oluşturur. Eğer yaparsanız a = [[0]*10]*10ve sonra a[0][0] = 1her satırdaki ilk öğenin 1'e eşit olduğunu göreceksiniz
andnik

0

lst = [[0] * m, i aralığında (n)]

tüm matrisi başlat n = satırlar ve m = sütunlar


Lütfen kodu kod olarak biçimlendirebilir misiniz? Çok daha okunaklı olurdu.
Thomas

0

Başka bir yol, iki boyutlu bir diziyi tutmak için bir sözlük kullanmaktır.

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

Bu sadece herhangi bir 1D, 2D değeri tutabilir ve bunu 0veya başka bir int değerine başlatmak için koleksiyonları kullanın .

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

0

Kod:

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 değişmez olmalı.


-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
Lütfen kodunuzun ne yaptığını açıklayan bir metin ekleyin.
whackamadoodle3000

1
Genellikle, bazı anonim kod satırlarını göndermek yerine bir çözümü açıklamak daha iyidir. İyi bir yanıtı nasıl yazarım ve ayrıca tamamen kod tabanlı cevapları açıklamayı okuyabilirsiniz .
Massimiliano Kraus
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.