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 :

pointeur de liste


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de racine carrée
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2018
    Messages
    156
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2018
    Messages : 156
    Par défaut pointeur de liste
    Bonjour à tous,
    pour les listes définies en compréhension, quel est le pointeur de la liste que l'on est en train de créer ? Je m'explique:
    Voilà un code qui permet d'ajouter des éléments à une liste si ces éléments ne sont pas déjà dans celle-ci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    l=['moto', 'omto', 'otmo', 'otom', 'mtoo', 'tmoo', 'tomo', 'toom', 'mtoo', 'tmoo', 'tomo', 'toom', 'moot', 'omot', 'oomt', 'ootm', 'moot', 'omot', 'oomt', 'ootm', 'moto', 'omto', 'otmo', 'otom']
    L=[]
    for k in l:
        if k not in L:
            L.append(k)
    je voudrais trouver un équivalent en compréhension à ce code du style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    L=[k for k in l if k not in self]
    où self serait une référence vers la liste que l'on est en train de créer, mais je ne sais pas quoi mettre à la place de self (cette liste n'a pas de nom puisqu'on ne l'a pas encore créée).

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Salut,

    Il y a peut être des hacks qui traînent sur Internet mais une compréhension de liste est une écriture condensée pour des cas simples. Une boucle "for" pour les autres cas fonctionne bien aussi.
    Ceci dit dans votre cas, vous pourriez construire un set (ce qui va gérer les doublons) puis en faire une liste: L = list(set(l)).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre confirmé Avatar de racine carrée
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2018
    Messages
    156
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2018
    Messages : 156
    Par défaut
    En fait c'est un exo dans le cadre de la prepa, et on n'a pas le droit d'utiliser les dictionnaires ni les sets.
    On devait faire une fonction anagramme récursive, et je m'étais donné comme objectifs de la faire en une seule ligne.
    Du coup j'ai réussi à faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    anag=lambda mot: [mot] if len(mot)==1 else [mot[k]+i for k in range(len(mot)) for i in anag(mot[:k]+mot[k+1:])]
    qui marche bien mais renvoie des doublons quand on cherche les anagrammes d'un mot contenant plusieurs fois la même lettre.
    On a pas le droits d'utiliser {}, sinon j'aurais fait le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    anag=lambda mot: {mot} if len(mot)==1 else {mot[k]+i for k in range(len(mot)) for i in anag(mot[:k]+mot[k+1:])}
    .
    J'ai donc rajouté une fonction lambda qui supprime tous les doublons au moment de renvoyer la liste:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    anag=lambda mot: [mot] if len(mot)==1 else (lambda l: [l[k] for k in range(len(l)) if l[k] not in l[:k]])([mot[k]+i for k in range(len(mot)) for i in anag(mot[:k]+mot[k+1:])])
    mais ça rallonge pas mal le temps de recherche, du coup je voulais trouver une solution pour tester si un élément est déjà dans la liste créée au moment de le rajouter, plutôt que de mettre tous les éléments et de supprimer ensuite ceux qui sont en trop.
    ça donnerait donc un code du style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    anag=lambda mot: [mot] if len(mot)==1 else [mot[k]+i for k in range(len(mot)) if (mot[k]+i for k in range(len(mot))) not in self for i in anag(mot[:k]+mot[k+1:])]
    Mais je crains que ce ne soit possible ...

  4. #4
    Membre chevronné
    Homme Profil pro
    Développeur banc de test
    Inscrit en
    Mai 2014
    Messages
    199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur banc de test
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mai 2014
    Messages : 199
    Par défaut
    Bonsoir,

    il y a une possibilité en utilisant locals() qui retourne toutes les déclarations locales d'une fonction.

    Testé sur Python 3.7 : La comprehension list va créer une variable ".0"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [locals() for i in [1]]
    [{'.0': <tuple_iterator object at 0x000000000303AEB8>, 'i': 1}]

    Ça génère un itérateur mais du coup on ne peut pas interroger l'itérateur sans le modifier.

    Le seul moyen est de copier l'itérateur avec (copy.copy) mais ça rallonge sacrément le temps d’exécution :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    from copy import copy
    [i for i in [3, 2, 1, 2, 1] if i not in copy(locals()['.0'])] # Retourne [3, 2, 1]
    Et le comportement est curieux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [i for i in [3, 2, 1, 2, 1, 3] if i not in copy(locals()['.0'])] # Retourne [2, 1, 3]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [i for i in [3, 2, 1, 2, 1, 3, 2] if i not in copy(locals()['.0'])] # Retourne [1, 3, 2]
    Il semble garder le dernier doublon plutôt que le premier

    Et question timing c'est clairement pas une solution à utiliser :


    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
    21
    22
    23
    24
    25
    26
    27
    import timeit
    from copy import copy
     
    l=['moto', 'omto', 'otmo', 'otom', 'mtoo', 'tmoo', 'tomo', 'toom', 'mtoo', 'tmoo', 'tomo', 'toom', 'moot', 'omot', 'oomt', 'ootm', 'moot', 'omot', 'oomt', 'ootm', 'moto', 'omto', 'otmo', 'otom']
     
    methode1 = """
    L = []
    for k in l:
        if k not in L:
            L.append(k)
    """
     
    methode2 = """[k for k in l if k not in copy(locals()['.0'])]"""
     
    nb_test = int(100e3)
    print("methode1")
    t = timeit.timeit(methode1, setup="from __main__ import l", number=nb_test)
    print("Temps d'éxecution : total: {:.02f} s, moyen : {:.02f} µs".format(
        t,
        (t / nb_test) * 1e6
    ))
    print("methode2")
    t = timeit.timeit(methode2, setup="from __main__ import l, copy", number=nb_test)
    print("Temps d'exécution : total: {:.02f} s, moyen : {:.02f} µs".format(
        t,
        (t / nb_test) * 1e6
    ))
    methode1 :
    Temps d’exécution : total: 0.38 s, moyen : 3.77 µs

    ['moto', 'omto', 'otmo', 'otom', 'mtoo', 'tmoo', 'tomo', 'toom', 'moot', 'omot', 'oomt', 'ootm']
    methode2:
    Temps d'exécution : total: 10.77 s, moyen : 107.69 µs

    ['mtoo', 'tmoo', 'tomo', 'toom', 'moot', 'omot', 'oomt', 'ootm', 'moto', 'omto', 'otmo', 'otom']
    Je me demande si j'utilise la bonne fonction pour copier l'itérateur car on dirait qu'il perd l'ordre.

  5. #5
    Membre confirmé Avatar de racine carrée
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2018
    Messages
    156
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2018
    Messages : 156
    Par défaut
    Merci beaucoup,
    j'aurai au moins appris comment on utilise timeit (je ne savais pas qu'on pouvait envoyer comme ça du code sous forme de chaine de caractères à une fonction.)
    Sinon tant pis pour la méthode sur une seule ligne, car c'était un objectif que je m'étais donné pour m'amuser.

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

Discussions similaires

  1. Pointeur sur List
    Par ludo00002 dans le forum Débuter
    Réponses: 7
    Dernier message: 08/01/2009, 10h47
  2. Pointeur dans liste ?
    Par eyquem dans le forum Général Python
    Réponses: 2
    Dernier message: 12/05/2008, 22h30
  3. Pointeurs et listes chaînées
    Par womannosky dans le forum C++
    Réponses: 8
    Dernier message: 11/11/2007, 04h41
  4. Réponses: 18
    Dernier message: 29/03/2007, 20h40
  5. [Débutant] Pointeur sur liste chainée
    Par HaTnuX dans le forum C
    Réponses: 2
    Dernier message: 02/12/2006, 17h53

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