1
votes

La liste 2D en Python répète les attributions de nombres aléatoires

Toutes mes excuses car je suis sûr que ce problème s'est déjà posé mais aucun des exemples ne semble s'appliquer.

J'essaie de créer une liste 2D (4 sur 100) qui attribue des valeurs aléatoires dans différentes plages dans chaque ligne.

29
21
2
0

29
21
2
0

Les sorties affichent simplement le même ensemble de nombres pour chaque ligne de la liste 2D ...

Sortie:

XXX

Je suis nouveau en python et je sais que je dois manquer quelque chose de fondamental, mais après beaucoup de umming et ahhing je ne l'ai pas compris, toute aide est appréciée. p >

Merci


2 commentaires

print ('\ n'.join ([' '. join ([' {} '.format (élément) pour l'élément dans la ligne]) pour la ligne dans la fleur])) cela peut également être utile


Copie possible de Liste des modifications de listes reflétées de manière inattendue dans les sous-listes


3 Réponses :


2
votes

Vous avez une liste qui contient 100 fois la même liste

import random

size_of_meadow = 100
no_of_flowers = 100
no_of_flower_types = 3

flower = []

for row in range(no_of_flowers):
  flower.append([random.randint(0, size_of_meadow-1),
      random.randint(0, size_of_meadow-1),
      random.randint(1, no_of_flower_types),
      1 if random.randint(0, 100) < 5 else 0])

print(flower[0][0])
print(flower[0][1])
print(flower[0][2])
print(flower[0][3])
print(" ")
print(flower[1][0])
print(flower[1][1])
print(flower[1][2])
print(flower[1][3])
# Sorry the above isn't in a for loop

La meilleure solution sera

a=[0,0,0]
flower=[a,a,a,a,...]

Cependant, le générateur de fleurs serait pair mieux


1 commentaires

C'est génial et a produit les résultats que je voulais. Je ne comprends toujours pas tout à fait l'erreur que je faisais, mais j'irai de l'avant en utilisant cette méthode à l'avenir.



2
votes

Hey @Lee a raison mais laissez-moi élaborer

flower = [[None for _ in range(5)] for _ in range(no_of_flowers)] 

>>> id(flower[0])
4354853832
>>> id(flower[1])
4354854600

Ici vous pouvez voir que chaque sous-liste pointera vers le même emplacement en mémoire

J'utiliserais cette méthode:

>>> flower = [[0] * 5] * 100
>>> flower[0]
[0, 0, 0, 0, 0]
>>> flower[1]
[0, 0, 0, 0, 0]
>>> id(flower[0])
4354853640
>>> id(flower[1])
4354853640


5 commentaires

C'est ce que je pensais, mais pourquoi tous indiquent-ils la même position? En fait, je m'attendais à ce que [[0] * 5] * 100 s'exécute de la même manière que votre code.


Cette réponse a produit le résultat que je voulais en changeant simplement la ligne de code, ce qui est génial.


@epsilonmajorquezero lorsque vous exécutez [0] * 5 , il crée une liste [0, 0, 0, 0, 0] puis le code * 100 crée une liste dont la sous-liste pointe sur 100 positions. La compilation de liste est en fait réexécutée à chaque itération en créant de nouveaux éléments


@bison qui a rendu le problème vraiment clair, merci pour l'explication


Ouais, je vois que c'est ce qu'il faut faire en fonction du comportement mais alors le comportement n'est pas vraiment cohérent: d'abord [0] * 5 qui crée une liste de 5 zéros (qui ne sont pas au même emplacement en mémoire) mais ensuite cette liste se multiplie indique à nouveau la même position.



3
votes

En utilisant [[0] * 5] * no_of_flowers , vous créez 100 références à la même liste. Cela signifie qu'il y a UNE SEULE RANGÉE dans la mémoire.

Lorsque vous modifiez une ligne, si affecte la ligne en mémoire, et puisque toutes les autres «lignes» y font référence, ils utiliseront simplement la liste en mémoire qui est à jour.

Pour éviter ce scénario, vous pouvez utiliser:

>>> board = [['']*3 for _ in range(3)]
>>> board[0][0] = "X"
>>> board
[['X', '', ''], ['', '', ''], ['', '', '']]

Vous pouvez trouver un exemple et explication en wtfpython :

XXX

Sortie:

>>> board
[['', '', ''], ['', '', ''], ['', '', '']]
>>> board[0]
['', '', '']
>>> board[0][0]
''
>>> board[0][0] = "X"
>>> board
[['X', '', ''], ['X', '', ''], ['X', '', '']]

Explication:

Lorsque nous initialisons la ligne , cette visualisation explique ce qui se passe dans la mémoire.

entrez la description de l'image ici

Et quand le board code> est initialisé en multipliant la ligne , c'est ce qui se passe à l'intérieur de la mémoire (chacun des éléments board [0] , board [1] code > et board [2] cod e> est une référence à la même liste référencée par row)

entrez la description de l'image ici

Nous pouvons éviter cela scénario ici en n'utilisant pas la variable row pour générer le board . (Question posée dans ce numéro).

# Let's initialize a row
row = [""]*3 #row i['', '', '']
# Let's make a board
board = [row]*3


0 commentaires