Journal Tableau à 2 dimensions

Posté par  (site web personnel) .
Étiquettes : aucune
0
13
août
2003
Bonjour,

Dans un programme, j'ai besoin de modéliser une carte en 2D donc j'utilise pour ça des listes imbriquées de la façon suivante

# Création de ma map
carte = []
iy = []
for y in range(30):
iy.append("t") # t signifie que la case en question est du terrain
for x in range(30):
carte.append(iy)

Pour modifier un emplacement je comptais faire la chose suivante :

carte[x][y] = f # pour placer à la case de coordonées (x,y) la lettre f # (pour fourmi)

Hors cela me change la valeur de y pour toutes les lignes de x, par exemple en supposant que j'ai le tableau suivant :

t t t t t
t t t t t
t t t t t

avec carte[2][2] = "f", je me retrouve avec le tableau suivant :

t t f t t
t t f t t
t t f t t

alors que je voudrais obtenir

t t t t t
t t t t t
t t f t t

Et je ne vois vraiment pas pourquoi ça me fais ça ;(

Merci
  • # Re: Tableau à 2 dimensions

    Posté par  . Évalué à 6.

    Quand tu fais

    for x in range(30):
    carte.append(iy)

    ca ajoute une référence/pointeur vers iy dans le tableau carte et non pas une copie de iy, donc si tu modifie une ligne tu modifie iy, c'est à dire toutes les lignes
    • [^] # Re: Tableau à 2 dimensions

      Posté par  . Évalué à 1.

      c'est exact donc fais ceci :

      # Création de ma map
      carte = []
      iy = []
      for y in range(30):
        iy.append("t")
        for x in range(30):
          carte.append(iy[:])

      iy[:] est une copie de iy
      l'ajout de "t" ajoute aussi des références vers la même chaîne "t" mais dans ce sens là, ça va
      • [^] # Re: Tableau à 2 dimensions

        Posté par  . Évalué à 1.

        ps : j'ai même pas vérifié l'algo, c'est juste pour te montrer l'astuce de la copie de liste

        sinon je te propose une technique dictionnairienne :

        carte = {}

        carte((x, y)) = "t"

        case = carte.setdefault((x,y), "t")

        vaut la valeur stockée à la clé (x, y) ou alors "t" par défaut

        si tu préfère la bonne vieille initialisation :

        carte = {}
        for y in range(30):
          for x in range(30):
            carte((x, y)) = "t"
  • # Re: Tableau à 2 dimensions

    Posté par  . Évalué à 3.

    Je ne sais pas ce que tu utilises comme langage, mais :
    1- tu ne construit qu'une seule variable iy
    2- dans ta boucle d'affectation 'carte.append(iy)', si iy est partage (alors que tu voudrais qu'il soit duplique), alors
    3- CQFD

    Donc, soit tu te debrouilles pour faire un truc du style :
    carte.append(iy.clone())
    ou
    carte.append(iy.copy())
    ou whatever du moment que tu duplique

    ou bien tu change ta boucle en : (duplication a la main)
    for x in range(30):
    {
    iy = []
    for y in range(30):
    {
    iy.append("t") # t signifie que la case en question est du terrain
    }
    carte.append(iy)
    }

    J'ai rajoute des accolades pour la clarte ...
  • # Re: Tableau à 2 dimensions

    Posté par  (site web personnel) . Évalué à 2.

    C'est dans quel langage ? (meme si la solution t'as deja été donnée)
    • [^] # Re: Tableau à 2 dimensions

      Posté par  (site web personnel) . Évalué à 1.

      Python

      Désolé, je l'avais oublié
    • [^] # Re: Tableau à 2 dimensions

      Posté par  . Évalué à 0.

      C'est dans quel langage ?

      pfff t'as même pas reconnu :)

      et pourtant... avec cette syntaxe claire et simple, à tel point que les gens* ont pu voir l'erreur d'algo sans connaître le langage, ça ne pouvait être que du python :)

      bon d'accord, templeet a viré l'identation...

      (*) oui bon, j'ai répondu trop vite mais je me suis rattrapé avec une autre solution :)
  • # Re: Tableau à 2 dimensions

    Posté par  (site web personnel) . Évalué à 0.

    alors que je voudrais obtenir

    t t t t t
    t t t t t
    t t f t t


    pas plutot ca ?
    t t t t t
    t t f t t
    t t f t t
  • # Merci à tous

    Posté par  (site web personnel) . Évalué à 2.

    ça fonctionne, merci à tous
  • # Python est formidable

    Posté par  . Évalué à 3.

    maître cappello : "il y a plus simple "

    x=['t']
    map=[]
    for i in xrange( 30 )
    .....map.append( x*30)

    et voilà
    • [^] # Re: Python est formidable

      Posté par  . Évalué à 2.

      mouarf j'y avais pas pensé non plus ! et pourtant je m'en étais déjà servi.

      ou sinon avec une variable de moins :

      map = []
      for i in range(30):
        map.append(['t] * 30)

      bon j'ai vérifié et ça utilise bien autant de références que d'itérations de i, contrairement à la première version.
    • [^] # Re: Python est formidable

      Posté par  . Évalué à 2.

      et juste pour le plaisir

      e=['t']
      carte = [e*30 for i in xrange(30)]
      • [^] # Re: Python est formidable

        Posté par  . Évalué à 2.

        arf j'allais proposer la même syntaxe mais pour écrire en une seule ligne :

        map = [['t'] * 30 for i in range(30)]

        bon on devrait arrêter là avant que les gens commencent à croire que python a les mêmes travers (de porc ?) que perl :)
        • [^] # Re: Python est formidable

          Posté par  . Évalué à 1.

          Trop tard :-)
          • [^] # Re: Python est formidable

            Posté par  . Évalué à 2.

            :)

            pour la peine je fais encore plus simple :

            carte = [['t'] * 30] * 30

            mouhahaha !

            et la version dictionnaire :

            carte = {}
            [carte.setdefault((x,y), 't') for x in range(30) for y in range(30)]

            bon il est temps que je rentre chez moi...
            • [^] # Re: Python est formidable

              Posté par  . Évalué à 3.

              carte = [['t'] * 30] * 30

              WAW, elle est superbe celle-là!

              Beaucoup plus compact que ce qu'on pourrais faire en C et beaucoup plus clair à la fois.
              • [^] # Re: Python est formidable

                Posté par  (site web personnel) . Évalué à 1.

                ben oui mais non parce que là il y a le même problème qu'avant, les lignes sont toutes le mêmes ...
                • [^] # Re: Python est formidable

                  Posté par  . Évalué à 1.

                  arf... pas vérifié !


                  'vais aller me fouetter tiens !

                  ou alors...

                  carte = [['t'][:] * 30][:] * 30

                  là je devrais être tranquille :)

                  heu... en fait je vais aller me coucher... la journée a été longue... connerie de rer !
                  • [^] # Re: Python est formidable

                    Posté par  (site web personnel) . Évalué à 2.

                    non ça ne change rien, (enfin si, ça fait 2 copies inutiles).

                    Pour moi, le plus simple reste :
                    [ ['t' for i in range(30)] for j in range(30) ]
                    ou à la rigueur :
                    [ ['t] * 30 for i in range(30) ]
  • # Démasqué !!!

    Posté par  (site web personnel) . Évalué à 1.

    Le message dans fr.comp.lang.python ne suffisait pas ?

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.