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 :

supprimer des doublons d'une liste


Sujet :

Python

  1. #41
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 78
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Par défaut
    @ phili_b
    Ta solution calcule le nombre d'occurrences de chaque élément de la liste par un appel à 'count'. Or nous n'avons rien à faire de ce nombre, nous voulons seulement savoir si un élément possède une autre occurrence.
    Donc, dans le genre (dédoublonnage 'en place'), je préfère:
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    L = ['a','b','c','b','d','a','e']
    n=len(L)
    i=0
    while i <=n-2:
        if L[i] in L[i+1:]:
            L.remove(L[i])
            n-=1
        else:
            i+=1
    print L
    @eyquem:
    Faudra bien que je lise ton post, mais pas ce soir (trop fatigué).
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  2. #42
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 78
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Par défaut
    Ah oui, groupby() m’a fait beaucoup phosphorer, à un moment.

    D’ailleurs je vois qu’il manque quelque chose dans ce code:
    quand on dit que l’ordre ne compte pas, c’est pour justifier l’emploi de sort()


    Il faut

    Code :

    from itertools import groupby

    def dedoublonne(l):
    l.sort()
    return [x[0] for x in groupby(l)]
    Après un appel à 'sort' l'utilisation de groupby est redondante et coûteuse.
    Faire plutôt, en utilisant une version simplifiée de mon exemple précédent:
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    L = ['a','b','c','b','d','a','e']
    L.sort()
    n=len(L)
    i=0
    while i <=n-2:
        if L[i] == L[i+1]:
            L.remove(L[i])
            n-=1
        else:
            i+=1
    print L
    qui garantit une efficacité en nlog(n)
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  3. #43
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Par défaut
    Citation Envoyé par Zavonen Voir le message
    Après un appel à 'sort' l'utilisation de groupby est redondante et coûteuse.
    Coûteuse, je ne sais pas.

    Redondante, sûrement pas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    >>> from itertools import groupby
    >>> [k for k, g in groupby('AAAABBBCCDAABBB')]
    ['A', 'B', 'C', 'D', 'A', 'B']
    >>> [k for k, g in groupby(sorted('AAAABBBCCDAABBB'))]
    ['A', 'B', 'C', 'D']
    Ok, j'ai utilisé sorted et pas sort, mais bon, c'était juste pour gagner 1 ligne.

    Edit : je me rends compte que j'ai écrit que l'utilisation de sort n'est pas redondante avant un appel à groupby alors que, Zavonen, tu estimes que l'appel à groupby après l'appel à sort est redondant.
    J'ai le sentiment d'avoir répondu légèrement à côté, mais bon, ce qui est écrit est écrit.

  4. #44
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Bonjour,
    voici une version TEXTE de ce qu'a proposé Zavoven :
    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
    #! /usr/bin/env python3
     
    def adHoc(text):
        iMax = len(text) - 1
        i = 0
     
        while i < iMax:
            if text[i] in text[i+1:]:
                text = text[i] + text.replace(text[i], '')
                iMax = len(text) - 1
            else:
                i += 1
     
        return text
     
    tests = [
              'A',
              'AA',
              'AB',
              'AAAABBBCCDAABBB',
           ]
     
    for oneTest in tests:
        print( '---',
               oneTest,
               'CHARACTERS USED ==> ' + adHoc(oneTest),
               sep = "\n" )
    Sous Python 3, on obtient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ---
    A
    CHARACTERS USED ==> A
    ---
    AA
    CHARACTERS USED ==> A
    ---
    AB
    CHARACTERS USED ==> AB
    ---
    AAAABBBCCDAABBB
    CHARACTERS USED ==> CBAD
    Au passage, dans le code Zavoven, on peut faire la nano-amélioration suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ...
    #n=len(L)
    n=len(L)-1
    i=0
    #while i <=n-2:
    while i < n:
       ...

  5. #45
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Par défaut
    Citation Envoyé par rambc Voir le message
    Bonjour,
    voici une version TEXTE de ce qu'a proposé Zavoven :


    Je ne comprends pas pourquoi tu fais cela.

    Le fichier zavonen.py
    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
    28
     
    #!/usr/bin/env python
    #coding: utf-8
     
    def zavonen(l):
        """
        Supprime les doublons d'une liste.
     
        Exemples:
        >>> zavonen([1, 2, 3, 4, 2, 3, 5])
        [1, 2, 3, 4, 5]
        >>> ''.join(zavonen(list('AAAABBBCCDAAABB')))
        'ABCD'
        """
        l.sort()
        n = len(l)
        i = 0
        while i <= n - 2:
            if l[i] == l[i + 1]:
                l.remove(l[i]) # ou l.pop(i)
                n -= 1
            else:
                i += 1
        return l
     
    if __name__ == '__main__':
        from doctest import testmod
        testmod(verbose=True)
    A l'exécution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Trying:
        zavonen([1, 2, 3, 4, 2, 3, 5])
    Expecting:
        [1, 2, 3, 4, 5]
    ok
    Trying:
        ''.join(zavonen(list('AAAABBBCCDAAABB')))
    Expecting:
        'ABCD'
    ok
    # du blabla dont on se fiche...
    Tu peux éventuellement faire une fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    def zavonentext(texte):
        return ''.join(zavonen(list(text)))
    De cette manière, tu évites la duplication du code et les futurs problèmes de maintenance inhérents.

    D'ailleurs, on peut même faire mieux:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    def zavonen(input):
        l = list(input)
        #le reste du code pareil
    De cette manière, on est assurés de travailler sur une liste et donc de ne pas avoir de problème sur le reste de la fonction.

    Pas très pythonique d'avoir une version d'une fonction par type possible d'argument.

    Ma version ultime serait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    def nodoublon(input):
        seen = []
        for x in input:
            if x not in seen:
                yield x
                seen.append(x)
    Ce qui ressemble diantrement à ce qui a déjà été proposé par je-ne-sais-plus-qui (désolé).

    Les points forts:
    1. on se fiche totalement du type de input : liste, tuple, string, générateur sont acceptés ;
    2. on retourne un générateur et on peut en faire ce qu'on veut : 1 liste (avec list(nodoublon(input))), une string (''.join(nodoublon(input)), voire ''.join(str(x) for x in nodoublon(input))), un tuple, un simple itérateur ( for x in nodoublon(input): dosomethingwith(x)) ;
    3. le code est self-explanatory et je ne me prendrais pas la tête dans 3 mois à le relire (commentaires et tests sout toutefois toujours les bienvenus, avec modération).

    Ne reste plus qu'à benchmarker tout cela, si la vitesse d'exécution est réellement importante (et, dans ce cas, je suppose que coder la fonction de zavonen dans un module Python écrit en C est la meilleure solution).

    Edit : à noter que la principale différence est que l'algo de Zavonen fait de la modification sur-place, pas le mien (ni aucun des autres présentés si je ne m'abuse). Je me pose des questions sur les avantages d'une telle méthode (ça veut pas dire que je trouve ça bête, juste que je ne connais pas les différences entre sur-place et pas-sur-place : contrainte temps ? contrainte mémoire ? beauté du geste ? autre ?)

  6. #46
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Citation Envoyé par nardo47 Voir le message


    Je ne comprends pas pourquoi tu fais cela.
    Juste pour le plaisir et aussi dans un contexte où on ne travaille que sur des chaînes.

Discussions similaires

  1. Comment supprimer des "0" dans une liste
    Par solorac dans le forum Excel
    Réponses: 4
    Dernier message: 04/09/2007, 13h22
  2. [DOM] Ajouter/supprimer des entrées d'une liste déroulante
    Par Zakapatul dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 16/05/2007, 11h25
  3. Réponses: 10
    Dernier message: 19/09/2006, 04h15
  4. Supprimer des éléments d'une liste
    Par espadon1 dans le forum Langage
    Réponses: 2
    Dernier message: 31/05/2006, 16h08
  5. [Collections]Supprimer des doublons dans une ArrayList
    Par emie31 dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 12/12/2005, 16h15

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