IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Iterator over lists comprehensions ?


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Par défaut Iterator over lists comprehensions ?
    Salut,

    Je débute en python, et pour apprendre, je veux faire quelque chose de très simple : générer toutes les combinaisons de plusieurs ensembles (numériques).

    Par exemple, je veux générer tous les vecteurs possibles, avec comme composante sur la 1ère dimension tout entier naturel inférieur à 2, et sur la 2e dimension tout entier naturel inférieur à 3.

    Voici ce que j'ai codé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    def vectors(dimensions, index=0):
        if index == len(dimensions):
            return [[]]
        return [[h] + t for h in range(dimensions[index]) for t in vectors(dimensions, index + 1)]
     
    print vectors([2,3])
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ./test.py
    [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2]]
    Ça marche avec n'importe quel nombre de dimensions, par exemple avec [2,3,2,2] :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ./test.py 
    [[0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 0, 1, 1], [0, 1, 0, 0], [0, 1, 0, 1], [0, 1, 1, 0], [0, 1, 1, 1], [0, 2, 0, 0], [0, 2, 0, 1], [0, 2, 1, 0], [0, 2, 1, 1], [1, 0, 0, 0], [1, 0, 0, 1], [1, 0, 1, 0], [1, 0, 1, 1], [1, 1, 0, 0], [1, 1, 0, 1], [1, 1, 1, 0], [1, 1, 1, 1], [1, 2, 0, 0], [1, 2, 0, 1], [1, 2, 1, 0], [1, 2, 1, 1]]
    Maintenant, je voudrais savoir si ce code rendu très court grâce aux "lists comprehensions" peut être transformé en iterator, c'est à dire sans générer la liste complète, mais seulement à la demande ?

    Est-il possible de combiner les deux (iterator + lists comprehensions) ?

    PS: Pour info, j'ai réussi à coder le même résultat en iterator, mais sans utiliser les "lists comprehensions" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class CursorGenerator:
     
        def __init__(self, dimensions):
            self.dimensions = dimensions
     
        def cursor_increment(self, cursor, index=-1):
            if cursor[index] >= self.dimensions[index] - 1:
                if index == - len(self.dimensions):
                    return False
                cursor[index] = 0
                return self.cursor_increment(cursor, index - 1)
            else:
                cursor[index] += 1
            return True
     
        def __iter__(self):
            cursor = [0] * len(self.dimensions)
            yield cursor
            while self.cursor_increment(cursor):
                yield cursor
    Merci de votre aide.

  2. #2
    Membre Expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Par défaut
    J'ai trouvé, grâce à la réactivité du chan IRC #python-fr :-)

    Il suffit de mettre des parenthèses au lieu des crochets.
    est une liste.
    est un générateur.

    Ainsi, voici le code modifié :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def vectors(dimensions, index=0):
        if index == len(dimensions):
            return [[]]
        return ([h] + t for h in xrange(dimensions[index]) for t in vectors(dimensions, index + 1))
     
    for v in vectors([2,3,2,2]):
        print v

  3. #3
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Bonsoir,

    Juste pour info, ton code utilise ce qu'on appelle une generator expression, mais on peut aussi coder explicitement un générateur avec le mot-clé yield, qui permet d'implémenter une forme de coroutine:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def vectors(dimensions, index=0):
        if index == len(dimensions):
            yield []
        else:
            for h in xrange(dimensions[index]):
                for t in vectors(dimensions, index+1):
                    yield [h] + t
    L'exécution du générateur vectors retourne un itérateur; chaque appel de next sur cet itérateur exécute le code jusqu'au prochain yield, retourne la valeur indiquée, et le contexte d'exécution est sauvé pour être restauré au prochain appel de next.

  4. #4
    Membre Expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Par défaut
    Oui, c'est d'ailleurs bien puissant les yield expressions.

    J'ai découvert et utilisé tout ça sur un solveur de cube-serpent : http://blog.rom1v.com/2011/09/resoud...ent-en-python/

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Can only iterate over an array or an instance of java.lang.Iterable
    Par hardokin dans le forum Collection et Stream
    Réponses: 7
    Dernier message: 28/08/2008, 14h05
  2. Copier un dictionnaire par une list comprehension
    Par Sve@r dans le forum Général Python
    Réponses: 6
    Dernier message: 12/05/2008, 10h25
  3. Réponses: 1
    Dernier message: 23/04/2008, 14h52
  4. Iterator sur list et fonction const
    Par Pierre.M dans le forum SL & STL
    Réponses: 2
    Dernier message: 16/04/2008, 20h50
  5. iterator de list i+=2
    Par vincent0 dans le forum C++
    Réponses: 2
    Dernier message: 24/06/2006, 12h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo