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?

Masoud Abasian
la source
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
1
Voir aussi la FAQ Python3 sur Comment créer une liste multidimensionnelle?
Kevin W Matthews

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.

Manny D
la source
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.

senderle
la source
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]]
Andrew Clark
la source
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)]
mripard
la source
@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.

enobayram
la source
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)]
wberry
la source
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

[[], [], []]
Fabien
la source
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
utdemir
la source
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é.

erreur inconnue
la source
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)
Manohar Reddy Poreddy
la source
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.

innov8
la source
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)

khaz
la source
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.

Michael
la source
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
user110954
la source
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)
Namrata Tolani
la source
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]

wsanders
la source
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.

alessadnro
la source
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],
   ...
Mohammad Mahdi KouchakYazdi
la source
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.

ptérodragon
la source
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

Saurabh Chandra Patel
la source
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]]
Nagendra Nigade
la source
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

和風 信使
la source
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)] 
Harsh Sharma
la source
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], []]
Meraj al Maksud
la source
1

Essaye ça:

rows = int(input('Enter rows\n'))
my_list = []
for i in range(rows):
    my_list.append(list(map(int, input().split())))
Ankit Sharma
la source
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]]
Vlad Bezden
la source
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.

Chandra Shekhar
la source