Comment définir un tableau à deux dimensions en Python


726

Je veux définir un tableau à deux dimensions sans longueur initialisée comme ceci:

Matrix = [][]

mais ça ne marche pas ...

J'ai essayé le code ci-dessous, mais c'est faux aussi:

Matrix = [5][5]

Erreur:

Traceback ...

IndexError: list index out of range

Quelle est mon erreur?


14
On ne définit pas de tableaux , ou toute autre chose. Vous pouvez cependant créer des séquences multidimensionnelles, comme le montrent les réponses ici. N'oubliez pas que les variables python ne sont pas typées, mais que les valeurs sont fortement typées.
SingleNegationElimination

1
Je suis confus. Venant d'autres langues: c'est une différence entre un tableau 1D contenant des tableaux 1D et un tableau 2D. Et AFAIK, il n'y a aucun moyen d'avoir un tableau multidimensionnel (ou une liste) en python. Devrait être dit ici ...
Dirk Reichel

Réponses:


1011

Vous essayez techniquement d'indexer un tableau non initialisé. Vous devez d'abord initialiser la liste externe avec des listes avant d'ajouter des éléments; Python appelle cette "compréhension de liste".

# Creates a list containing 5 lists, each of 8 items, all set to 0
w, h = 8, 5;
Matrix = [[0 for x in range(w)] for y in range(h)] 

Vous pouvez maintenant ajouter des éléments à la liste:

Matrix[0][0] = 1
Matrix[6][0] = 3 # error! range... 
Matrix[0][6] = 3 # valid

Notez que la matrice est une adresse "y" majeure, en d'autres termes, "l'index y" précède l '"index x".

print Matrix[0][0] # prints 1
x, y = 0, 6 
print Matrix[x][y] # prints 3; be careful with indexing! 

Bien que vous puissiez les nommer comme vous le souhaitez, je le vois de cette façon pour éviter toute confusion qui pourrait survenir avec l'indexation, si vous utilisez "x" pour les listes intérieure et extérieure et que vous voulez une matrice non carrée.


219
[[0 pour x dans la plage (cols_count)] pour x dans la plage (row_count)]
songhir

3
Modification étrange par ademar111190. En Python 3, il n'y a pas de xrange mais si vous devez utiliser Python 2, alors xrange est la fonction correcte à utiliser si vous ne voulez pas créer inutilement des objets.
Dave

4
@dave Si vous n'en avez pas besoin, vous pouvez utiliser rangepour créer directement les listes internes:[range(5) for x in range(5)]
alanjds

2
@alanjds - c'est vrai, mais vous créez toujours potentiellement de nombreuses références d'objets inutiles en Python 2 pour l'itération externe (essayez ceci avec une plage TRÈS large). De plus, l'initialisation à une certaine valeur est presque toujours ce que vous voulez - et c'est souvent 0. range donne une collection itérable - xrange retourne un générateur. Mon point était qu'Ademar "corrigeait" quelque chose qui était en fait plus généralement correct et efficace que sa correction.
Dave

10
@ 6packkid la [0] * wpartie est agréable, mais [[0] * w] * h]produira un comportement inattendu. Essayez mat = [[0] * 3] * 3; mat[0][1] = 10; print(mat == [[0, 10, 0], [0, 10, 0], [0, 10, 0]])et mat = [[0] * 3 for i in range(3)]; mat[0][1] = 10; print(mat == [[0, 10, 0], [0, 0, 0], [0, 0, 0]]).
senderle

408

Si vous voulez vraiment une matrice, vous feriez peut-être mieux de l'utiliser numpy. Les opérations matricielles numpyutilisent le plus souvent un type de tableau à deux dimensions. Il existe de nombreuses façons de créer un nouveau tableau; l'une des plus utiles est la zerosfonction, qui prend un paramètre de forme et renvoie un tableau de la forme donnée, avec les valeurs initialisées à zéro:

>>> import numpy
>>> numpy.zeros((5, 5))
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.]])

Voici quelques autres façons de créer des matrices et matrices 2D (avec sortie supprimée pour des raisons de compacité):

numpy.arange(25).reshape((5, 5))         # create a 1-d range and reshape
numpy.array(range(25)).reshape((5, 5))   # pass a Python range and reshape
numpy.array([5] * 25).reshape((5, 5))    # pass a Python list and reshape
numpy.empty((5, 5))                      # allocate, but don't initialize
numpy.ones((5, 5))                       # initialize with ones

numpyfournit également un matrixtype, mais il n'est plus recommandé pour aucune utilisation et peut être supprimé numpyà l'avenir.


80
Chaque fois que vous voulez des matrices, vous voulez utiliser numpy. Cette réponse devrait être la première.
Pat B

3
Le fait que la question utilise le mot anglais "matrix" ne signifie pas qu'ils doivent utiliser np.matrixpour la représenter. La bonne façon de représenter une matrice en numpy est avec un array.
user2357112 prend en charge Monica

@ user2357112, et comme vous pouvez le voir, la plupart des exemples répertoriés ci-dessus affichent des sorties arrayau lieu de matrices. Bien que cela ne soit pas toujours encouragé, il existe des raisons légitimes d'utiliser matrix- des questions de contexte.
senderle

1
@senderle, pouvez-vous développer les raisons d'utiliser matrix? Depuis que l' @opérateur a été introduit, il semble y avoir une raison de moins depuis que ce message a été écrit.
jpp

1
@jpp, comme le postait précédemment, les personnes venant de matlab pourraient le trouver utile. Mais les numpydocuments indiquent maintenant que la classe peut être obsolète et supprimée à l'avenir, donc je l'ai retirée de la réponse.
senderle

337

Voici une notation plus courte pour initialiser une liste de listes:

matrix = [[0]*5 for i in range(5)]

Malheureusement, le raccourcir en quelque chose comme 5*[5*[0]]ça ne fonctionne pas vraiment parce que vous vous retrouvez avec 5 copies de la même liste, donc quand vous en modifiez une, elles changent toutes, par exemple:

>>> matrix = 5*[5*[0]]
>>> matrix
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
>>> matrix[4][4] = 2
>>> matrix
[[0, 0, 0, 0, 2], [0, 0, 0, 0, 2], [0, 0, 0, 0, 2], [0, 0, 0, 0, 2], [0, 0, 0, 0, 2]]

4
Pourriez-vous expliquer la logique de l'échec du "raccourcissement"? Pourquoi python génère-t-il des copies de la même liste dans ce cas, et un tableau de cellules différentes dans le cas de [0]*5?
mike622867 du

12
Les commentaires ci-dessus ne sont pas exactement vrais: [0] * 5 crée toujours une séquence avec 5 fois une référence au même objet représentant le nombre 0. Mais vous ne le remarquerez jamais parce que 0 est immuable (je dirais que 0 se comporte comme une valeur - ou vous pouvez le considérer comme un type de données primitif - car il est immuable, vous n'avez donc jamais de problèmes avec les références au même objet au lieu d'en avoir des copies.)
dreua

4
plus pythonique: [[0]*5 for _ in range(5)]avec le compteur de boucles anonyme que vous n'utilisez pas
Jean-François Fabre

Ravi que vous signaliez le problème de la copie superficielle dans le deuxième exemple.
whatacold

merci @dreua, j'étais vraiment confus comment cela [0]*5fonctionne très bien. Maintenant, je comprends aussi pourquoi ce [{0}]*8serait une mauvaise idée.
kuku

110

Si vous souhaitez créer une matrice vide, la syntaxe correcte est

matrix = [[]]

Et si vous voulez générer une matrice de taille 5 remplie de 0,

matrix = [[0 for i in xrange(5)] for i in xrange(5)]

@KorayTugay Parce que la matrice est représentée à l'aide de liste (s) Python (les lignes) imbriquées dans une autre liste (les colonnes).
elig

2
Pour Python-3, utilisez la fonction de plage à la place de xrange func
Rakesh Chaudhari

77

Si tout ce que vous voulez, c'est un conteneur à deux dimensions pour contenir certains éléments, vous pouvez facilement utiliser un dictionnaire à la place:

Matrix = {}

Ensuite, vous pouvez faire:

Matrix[1,2] = 15
print Matrix[1,2]

Cela fonctionne car 1,2est un tuple, et vous l'utilisez comme clé pour indexer le dictionnaire. Le résultat est similaire à une matrice creuse et muette.

Comme indiqué par osa et Josap Valls, vous pouvez également utiliser Matrix = collections.defaultdict(lambda:0)pour que les éléments manquants aient une valeur par défaut de 0.

Vatsal souligne en outre que cette méthode n'est probablement pas très efficace pour les grandes matrices et ne devrait être utilisée que dans les parties non critiques des performances du code.


2
Ensuite, vous pouvez également faire import collections; Matrix = collections.defaultdict(float), pour substituer des zéros aux éléments non initialisés.
OSA

2
L'accès à un dict pour tuple (1,2) comme clé n'aurait pas la pire complexité d'O (n). Comme en interne, il hacherait les tuples. Alors que l'utilisation d'un tableau 2D donnerait une complexité temporelle de O (1) pour accéder à l'index [1,2]. Donc, utiliser dict pour cela ne devrait pas être un bon choix.
Vatsal

@Vatsal wiki.python.org/moin/TimeComplexity dit que le cas moyen est O (1), mais vous avez raison sur le pire des cas. Quoi qu'il en soit, à moins que vous ne parliez de BEAUCOUP D'ARTICLES, vous ne vous soucieriez pas de cette différence. En fait, je serais plus préoccupé par la mémoire que par le temps d'accès.
enobayram

De plus, nous essayons toujours d'éviter l'utilisation de dict jusqu'à ce que la complexité globale de l'algorithme soit égale ou supérieure à O (n ^ 2). Comme un 'n' fois O (n) les accès donneraient une complexité O (n ^ 2).
Vatsal

@enobayram, Désolé mais je ne suis pas d'accord. L'analyse asymptotique donnera toujours O (n ^ 2), si un accès O (n) dans le pire des cas est effectué 'n' fois. Là où l'analyse amortie peut donner une limite moindre. Et il y a une énorme différence entre le cas amorti et le cas moyen ... veuillez vous référer avant de faire des hypothèses et des commentaires vagues
Vatsal

42

En Python, vous allez créer une liste de listes. Vous n'avez pas à déclarer les dimensions à l'avance, mais vous le pouvez. Par exemple:

matrix = []
matrix.append([])
matrix.append([])
matrix[0].append(2)
matrix[1].append(3)

Maintenant matrice [0] [0] == 2 et matrice [1] [0] == 3. Vous pouvez également utiliser la syntaxe de compréhension de liste. Cet exemple l'utilise deux fois pour créer une "liste bidimensionnelle":

from itertools import count, takewhile
matrix = [[i for i in takewhile(lambda j: j < (k+1) * 10, count(k*10))] for k in range(10)]

6
extendserait également utile dans le premier cas: si vous commencez par m = [[]], vous pouvez ajouter à la liste interne (étendre une ligne) avec m[0].extend([1,2])et ajouter à la liste externe (ajouter une nouvelle ligne) avec m.append([3,4]), ces opérations vous laisseront avec [[1, 2], [3, 4]].
askewchan

22

La réponse acceptée est bonne et correcte, mais il m'a fallu un certain temps pour comprendre que je pouvais également l'utiliser pour créer un tableau complètement vide.

l =  [[] for _ in range(3)]

résulte en

[[], [], []]

22

Vous devriez faire une liste de listes, et la meilleure façon est d'utiliser des compréhensions imbriquées:

>>> matrix = [[0 for i in range(5)] for j in range(5)]
>>> pprint.pprint(matrix)
[[0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0]]

Sur votre [5][5]exemple, vous créez une liste avec un entier "5" à l'intérieur et essayez d'accéder à son 5ème élément, ce qui déclenche naturellement une IndexError car il n'y a pas de 5ème élément:

>>> l = [5]
>>> l[5]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

En fait, la séquence pour row_index ('i') et column_index ('j') est la suivante: '>>> matrix = [[0 pour column_index dans la plage (5)] pour row_index dans la plage (5)]'
Aniruddha Kalburgi

22
rows = int(input())
cols = int(input())

matrix = []
for i in range(rows):
  row = []
  for j in range(cols):
    row.append(0)
  matrix.append(row)

print(matrix)

Pourquoi un code aussi long, que Pythonvous demandez aussi?

Il y a longtemps, quand je n'étais pas à l'aise avec Python, j'ai vu les réponses sur une seule ligne pour écrire une matrice 2D et je me suis dit que je n'utiliserais plus la matrice 2D en Python. (Ces lignes simples étaient assez effrayantes et cela ne m'a donné aucune information sur ce que faisait Python. Notez également que je ne suis pas au courant de ces raccourcis.)

Quoi qu'il en soit, voici le code pour un débutant dont les origines C, CPP et Java

Remarque pour les amateurs et les experts de Python: veuillez ne pas voter contre simplement parce que j'ai écrit un code détaillé.


13

Une réécriture pour une lecture facile:

# 2D array/ matrix

# 5 rows, 5 cols
rows_count = 5
cols_count = 5

# create
#     creation looks reverse
#     create an array of "cols_count" cols, for each of the "rows_count" rows
#        all elements are initialized to 0
two_d_array = [[0 for j in range(cols_count)] for i in range(rows_count)]

# index is from 0 to 4
#     for both rows & cols
#     since 5 rows, 5 cols

# use
two_d_array[0][0] = 1
print two_d_array[0][0]  # prints 1   # 1st row, 1st col (top-left element of matrix)

two_d_array[1][0] = 2
print two_d_array[1][0]  # prints 2   # 2nd row, 1st col

two_d_array[1][4] = 3
print two_d_array[1][4]  # prints 3   # 2nd row, last col

two_d_array[4][4] = 4
print two_d_array[4][4]  # prints 4   # last row, last col (right, bottom element of matrix)

13

Utilisation:

matrix = [[0]*5 for i in range(5)]

Le * 5 pour la première dimension fonctionne car à ce niveau les données sont immuables.


5
J'écrirais probablement ceci commematrix = [[0]*cols for _ in range(rows)]
Shital Shah

12

Pour déclarer une matrice de zéros (uns):

numpy.zeros((x, y))

par exemple

>>> numpy.zeros((3, 5))
    array([[ 0.,  0.,  0.,  0.,  0.],
   [ 0.,  0.,  0.,  0.,  0.],
   [ 0.,  0.,  0.,  0.,  0.]])

ou numpy.ones ((x, y)) par exemple

>>> np.ones((3, 5))
array([[ 1.,  1.,  1.,  1.,  1.],
   [ 1.,  1.,  1.,  1.,  1.],
   [ 1.,  1.,  1.,  1.,  1.]])

Même trois dimensions sont possibles. ( http://www.astro.ufl.edu/~warner/prog/python.html voir -> Tableaux multidimensionnels)


12

C'est ainsi que je crée habituellement des tableaux 2D en python.

col = 3
row = 4
array = [[0] * col for _ in range(row)]

Je trouve cette syntaxe facile à retenir par rapport à l'utilisation de deux boucles for dans une compréhension de liste.


11

Je suis sur mon premier script Python, et j'étais un peu confus par l'exemple de la matrice carrée, donc j'espère que l'exemple ci-dessous vous aidera à gagner du temps:

 # Creates a 2 x 5 matrix
 Matrix = [[0 for y in xrange(5)] for x in xrange(2)]

pour que

Matrix[1][4] = 2 # Valid
Matrix[4][1] = 3 # IndexError: list index out of range

10

En utilisant NumPy, vous pouvez initialiser une matrice vide comme ceci:

import numpy as np
mm = np.matrix([])

Et plus tard, ajoutez des données comme ceci:

mm = np.append(mm, [[1,2]], axis=1)

quels seraient les avantages et les inconvénients de l'utilisation de numpy plutôt que de la "compréhension de liste"?
Revolucion pour Monica

7

Je lis dans des fichiers séparés par des virgules comme ceci:

data=[]
for l in infile:
    l = split(',')
    data.append(l)

La liste "data" est alors une liste de listes avec des données d'index [row] [col]


7

Si vous voulez pouvoir le penser comme un tableau 2D plutôt que d'être contraint de penser en termes de liste de listes (beaucoup plus naturel à mon avis), vous pouvez faire ce qui suit:

import numpy
Nx=3; Ny=4
my2Dlist= numpy.zeros((Nx,Ny)).tolist()

Le résultat est une liste (pas un tableau NumPy), et vous pouvez remplacer les positions individuelles par des nombres, des chaînes, etc.


sont numpy.matrixéquivalents à numpy.zerossans zéros sans être listés?
Revolucion pour Monica

6

C'est pour ça que le dictionnaire est fait!

matrix = {}

Vous pouvez définir des clés et des valeurs de deux manières:

matrix[0,0] = value

ou

matrix = { (0,0)  : value }

Résultat:

   [ value,  value,  value,  value,  value],
   [ value,  value,  value,  value,  value],
   ...

6

Utilisation:

import copy

def ndlist(*args, init=0):
    dp = init
    for x in reversed(args):
        dp = [copy.deepcopy(dp) for _ in range(x)]
    return dp

l = ndlist(1,2,3,4) # 4 dimensional list initialized with 0's
l[0][1][2][3] = 1

Je pense que NumPy est la voie à suivre. Ce qui précède est générique si vous ne souhaitez pas utiliser NumPy.


J'aime cette tentative de faire quelque chose de simple avec Python vanilla sans avoir à utiliser numpy.
Rick Henderson

4

en utilisant la liste:

matrix_in_python  = [['Roy',80,75,85,90,95],['John',75,80,75,85,100],['Dave',80,80,80,90,95]]

en utilisant dict: vous pouvez également stocker ces informations dans la table de hachage pour une recherche rapide comme

matrix = { '1':[0,0] , '2':[0,1],'3':[0,2],'4' : [1,0],'5':[1,1],'6':[1,2],'7':[2,0],'8':[2,1],'9':[2,2]};

la matrice ['1'] vous donnera le résultat en O (1) temps

* nb : vous devez gérer une collision dans la table de hachage


4

Si vous n'avez pas d'informations sur la taille avant de commencer, créez deux listes unidimensionnelles.

list 1: To store rows
list 2: Actual two-dimensional matrix

Stockez la ligne entière dans la 1ère liste. Une fois terminé, ajoutez la liste 1 à la liste 2:

from random import randint

coordinates=[]
temp=[]
points=int(raw_input("Enter No Of Coordinates >"))
for i in range(0,points):
    randomx=randint(0,1000)
    randomy=randint(0,1000)
    temp=[]
    temp.append(randomx)
    temp.append(randomy)
    coordinates.append(temp)

print coordinates

Production:

Enter No Of Coordinates >4
[[522, 96], [378, 276], [349, 741], [238, 439]]

3
# Creates a list containing 5 lists initialized to 0
Matrix = [[0]*5]*5

Faites attention à cette courte expression, voir l'explication complète dans la réponse de @ FJ


19
Soyez prudent de cette façon, car Matrix[0], Matrix[1], ..., Matrix[4]tous pointent vers le même tableau, donc après Matrix[0][0] = 3, vous vous attendez Matrix[0][0] == Matrix[1][0] == ... == Matrix[4][0] == 3.
gongzhitaao

1
Merci gongzhitaao pour ton commentaire. Si je l'avais lu plus longtemps, cela m'aurait fait gagner au moins une demi-heure. Avoir une matrice où chaque ligne pointe vers le même endroit en mémoire ne semble pas être très utile, et si vous n'êtes pas au courant de ce que vous faites c'est même dangereux! Je suis sûr que ce n'est PAS ce que Masoud Abasian, qui a posé la question, veut faire.
Adrian

7
Vous devez supprimer cette réponse, car ce n'est pas la bonne réponse. Les débutants peuvent être confus.
cxxl

2
De quelle réponse parlez-vous? Je ne vois pas d'utilisateur avec le nom "FJ" (même pas dans les réponses supprimées).
Peter Mortensen

3
l=[[0]*(L) for _ in range(W)]

Sera plus rapide que:

l = [[0 for x in range(L)] for y in range(W)] 

2
Répétition d'une réponse déjà donnée ci-dessous. Il [[0]*(L) for i in range(W)]devrait également être utilisé [[0]*(L) for _ in range(W)]car in'est utilisé nulle part
Ayush Vatsyayan

2

Vous pouvez créer une liste bidimensionnelle vide en imbriquant au moins deux contreventements carrés ou un troisième crochet ( []séparés par une virgule) avec un contreventement carré, comme ci-dessous:

Matrix = [[], []]

Supposons maintenant que vous vouliez ajouter 1 à Matrix[0][0]puis tapez:

Matrix[0].append(1)

Maintenant, tapez Matrix et appuyez sur Entrée. La sortie sera:

[[1], []]

1

Essaye ça:

rows = int(input('Enter rows\n'))
my_list = []
for i in range(rows):
    my_list.append(list(map(int, input().split())))

1

Si vous avez besoin d'une matrice avec des nombres prédéfinis, vous pouvez utiliser le code suivant:

def matrix(rows, cols, start=0):
    return [[c + start + r * cols for c in range(cols)] for r in range(rows)]


assert matrix(2, 3, 1) == [[1, 2, 3], [4, 5, 6]]

1

Voici l'extrait de code pour créer une matrice en python:

# get the input rows and cols
rows = int(input("rows : "))
cols = int(input("Cols : "))

# initialize the list
l=[[0]*cols for i in range(rows)]

# fill some random values in it
for i in range(0,rows):
    for j in range(0,cols):
        l[i][j] = i+j

# print the list
for i in range(0,rows):
    print()
    for j in range(0,cols):
        print(l[i][j],end=" ")

Veuillez suggérer si j'ai oublié quelque chose.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.