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 :

Dictionnaires, Tuples et Listes


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 13
    Par défaut Dictionnaires, Tuples et Listes
    Bonsoir,

    Une nouvelle question me turlupine.

    Voici le code suivant :

    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
    # -*- coding: iso-8859-1 -*-
    import codecs
    f=codecs.open('french.txt','r',encoding='iso-8859-1') 
    data=f.read()
    from nltk.tokenize import WordTokenizer 
    tokenizer=WordTokenizer() 
    words=tokenizer.tokenize(data)
    dico = {}
    for word in words:
        if word in dico:    
            dico[word]+=1   
        else: dico[word]=1
     
    lst=[(count, word) for word, count in dico.iteritems()]
    lst.sort(reverse=True)
    Nous avons donc un fichier texte tokenisé (séparé en mots/tokens). La liste de mots obtenue est utilisée par un dictionnaire pour compter le nombre d'occurrences de chaque mot dans le texte.

    J'aimerais obtenir la liste des mots revenants 15 fois ou plus dans le texte.

    Là actuellement, je sais extraire les données de mon dico dans une liste avec des couples nombre d'occurrences / mot, et je peux classer cette liste de façon à ce que les mots les plus fréquents apparaissent en tête, ou l'inverse.

    Mes problèmes:
    - Je n'arrive pas à couper cette liste au bon endroit automatiquement (Je peux toujours avoir un résultat en la coupant à la main avec des tranches du genre [0:400] pour faire en sorte de n'avoir plus que les mots qui reviennent plus de 15 fois mais c'est pas vraiment la bonne méthode à mon avis :p).
    Je me demande s'il y a un moyen de couper en mettant par exemple une condition : count>= à 15 ? Si oui ça se passe au moment où on extrait les données du dico ou ça se fait plus loin directement sur la liste de couples ?
    Peut on directement extraire uniquement les mots du dictionnaire avec cette condition là où faut il passer par deux étapes ?

    - Le problème que je rencontre ensuite en ayant coupé ma liste via système D (tranches), c'est que j'aimerais appliquer diverses transformations aux mots de celles cis. Mais pour cela il me faut uniquement des mots et non pas des couples avec les nombres d'occurrences qui persistent toujours :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for word in lst:
                 print word
    M'imprime toujours les couples entiers et non pas seulement les mots comme j'aurais pu l'espérer.
    J'ai lu partout que "Les tuples ne sont pas modifiables." mais est ce que cette 'liste' est vraiment un tuple ?

    Bref je patauge dans les différents types et je rame avec cette liste.

  2. #2
    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
    Pour ne garder que les mots avec 15 occurences ou plus:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    lst=[(count, word) for word, count in dico.iteritems() if count >= 15]
    lst.sort(reverse=True)
    # Pour n'extraire que les mots:
    lst = [word for _, word in lst]
    Maintenant, dans ton message tu ne dis pas si le tri est réellement nécessaire ou si tu ne l'utilisais que comme un moyen de filtrer sur count >=15 (alors qu'il n'est pas nécessaire pour cela).
    Si le tri n'est pas nécessaire, c'est encore plus simple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    lst = [word for word, count in dico.iteritems() if count >= 15]
    Le fait que les tuples ne sont pas modifiables n'a rien à voir ici. Ce que tu as c'est une liste de tuples. La liste est modifiable, ce qui veut dire que tu peux ajouter/supprimer/changer un élément de la liste (donc un tuple ici). Le tuple lui-même n'est pas modifiable, on ne peut donc pas ajouter, supprimer, ou changer un élément d'un tuple en place. Mais on peut en extraire les éléments et créer un nouveau tuple.
    Exemple:
    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
    # Une liste qui contient un tuple:
    >>> lst = [(1,"a")]
    # la liste est modifiable:
    >>> lst[0] = (2,"b")
    >>> lst
    [(2, 'b')]
    # pas le tuple qu'elle contient:
    >>> lst[0][0] = 3
    Traceback (most recent call last):
      File "<interactive input>", line 1, in <module>
    TypeError: 'tuple' object does not support item assignment
    # mais on peut tout de même en extraire les éléments:
    >>> lst[0] = (3,lst[0][1])
    >>> lst
    [(3, 'b')]

  3. #3
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Quelques remarques.

    Pour construire ton dictionnaire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for word in words:
        dico[word]  = dico.get(word,0) + 1
    Exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    dico = dict(zip(['amibe','zorro','sac'],[1,8,3]))
    print 'dico =',dico
    c = ['amibe','zorro','sac','rien','mer','ciel','toit','mine','col']
    for word in c:   
        dico[word] = dico.get(word,0) + 1
    print '\ndico =',dico
    dico = {'sac': 3, 'amibe': 1, 'zorro': 8}

    dico = {'toit': 1, 'amibe': 2, 'rien': 1, 'ciel': 1, 'sac': 4, 'zorro': 9, 'mine': 1, 'mer': 1, 'col': 1}


    Pour connaître le type d'une variable: print type()
    Pour changer une liste en tuple: tuple()
    Pour changer un tuple en liste: list()



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    a = [2,34,67,3,8,490]
    print 'a = %s type(a) = %s' % (a,type(a))
    h = tuple(a)
    print 'h = tuple(a)'
    print 'h = %s type(h) = %s' % (h,type(h))
    print
     
    b = (2,'merou',56,1,12)
    print 'b = %s type(b) = %s' % (b,type(b))
    g = list(b)
    print 'g = list(b)'
    print 'g = %s type(g) = %s' % (g,type(g))
    a = [2, 34, 67, 3, 8, 490] type(a) = <type 'list'>
    h = tuple(a)
    h = (2, 34, 67, 3, 8, 490) type(h) = <type 'tuple'>

    b = (2, 'merou', 56, 1, 12) type(b) = <type 'tuple'>
    g = list(b)
    g = [2, 'merou', 56, 1, 12] type(g) = <type 'list'>



    J'ignorais que sort() trie les éléments d'une liste sur la base du premier item de chaque élément si les éléments sont eux mêmes des séquences

    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
    print '================='
    a = ['a','lki','xvcbfg','hjuyi','op']
    b = [4,7,39,23,1]
    c = ['amibe','rien','mer','ciel','col']
    wu = [(a[i],b[i],c[i]) for i in xrange(5)]
    wu.sort()
    tu = tuple(wu)
    print 'type(tu) =',type(tu),'\n  tu =',tu
    print '================='
    a = ['a','lki','xvcbfg','hjuyi','op']
    b = [4,7,39,23,1]
    c = ['amibe','rien','mer','ciel','col']
    wu = [(b[i],c[i],a[i]) for i in xrange(5)]
    wu.sort()
    tu = tuple(wu)
    print 'type(tu) =',type(tu),'\n  tu =',tu
    =================
    type(tu) = <type 'tuple'>
    tu = (('a', 4, 'amibe'), ('hjuyi', 23, 'ciel'), ('lki', 7, 'rien'), ('op', 1, 'col'), ('xvcbfg', 39, 'mer'))
    =================
    type(tu) = <type 'tuple'>
    tu = ((1, 'col', 'op'), (4, 'amibe', 'a'), (7, 'rien', 'lki'), (23, 'ciel', 'hjuyi'), (39, 'mer', 'xvcbfg'))

  4. #4
    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
    J'ignorais que sort() trie les éléments d'une liste sur la base du premier item de chaque élément si les éléments sont eux mêmes des séquences
    Ce n'est pas tout à fait ça; sort utilise la relation d'ordre défini entre les éléments. Sur les séquences (de mêmes types), c'est l'ordre lexicographique qui est utilisé, comme pour les string. Ce qui est censé, puisque après tout, le type string est un type de séquence. Donc la comparaison se fait sur le premier élément de chaque séquence à comparer, mais si ceux-ci sont égaux, le second élément est comparé, etc.

    La méthode sort peut recevoir en argument une autre fonction de comparaison (argument nommé cmp), ou bien, ce qui revient au même mais est souvent plus efficace, une fonction qui retourne une clé de comparaison pour un élément donné (argument key).

    Par exemple, pour obtenir la liste de mots triée par nombre d'occurrences croissant à partir du dictionnaire (ce n'est pas le problème du PO mais c'est pour que l'exemple reste simple), on pourrait écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    lst = dico.keys()
    lst.sort(key = lambda x: dico[x])
    # ou bien
    lst.sort(cmp = lambda x,y: cmp(dico[x],dico[y]))
    Dans les anciennes versions de Python, ces arguments optionnels n'existaient pas et il fallait donc trouver un autre moyen; ce moyen exploite le fait que la comparaison de séquences se fait dans l'ordre lexicographique. On appelle cela le pattern 'decorate-sort-undecorate' ou encore (pour frimer en société) la "Schwartzian Transform".

    A partir d'une liste que l'on veut trier sur une clé particulière, l'idée est de précalculer les clés de comparaison pour chaque élément, remplacer les éléments de la liste par des tuples (clé, élément) (decorate), trier la liste (sort), et extraire les éléments en préservant l'ordre du tri (undecorate). Avec l'exemple précédent, cela donnerait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    lst = [(count, word) for word, count in dico.iteritems()]
    lst.sort()
    lst = [word for _,word in lst] # ou bien: lst = zip(*lst)[1]
    Cette technique présente un autre avantage, qui fait qu'elle est toujours utilisée aujourd'hui: elle est parfois plus rapide que de passer un fonction key en argument. Car le calcul de la clé à partir de l'élément n'est fait qu'une seule fois par élément, alors que la fonction key peut potentiellement être appelée plusieurs fois pour le même élément lors du tri, et l'appel d'une fonction est une opération relativement coûteuse en Python.

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Merci bien pour ces explications en profondeur.
    Je n'ai pas tout assimilé d'un coup, je les garde sous le coude pour les creuser.

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 99
    Par défaut
    Ah, je n'avais pas pensé à cette utilisation de la variable '_' dans le cadre d'une list comprehension (ou autre, d'ailleurs). Bien vu.

    En tout cas merci pour les explications sur le tri, je ne connaissais pas le nom pour "faire bien en société" du decorate-sort-undecorate ^^.

Discussions similaires

  1. [Python 3.X] Suppression d'un dictionnaire dans une liste
    Par Mima19 dans le forum Général Python
    Réponses: 5
    Dernier message: 06/04/2015, 07h25
  2. [Python 3.X] Passer dictionnaire dans une liste
    Par Mima19 dans le forum Général Python
    Réponses: 4
    Dernier message: 25/03/2015, 16h58
  3. des dictionnaires dans une liste
    Par jeannoel05 dans le forum Général Python
    Réponses: 18
    Dernier message: 21/05/2014, 00h19
  4. [WD-2010] dictionnaire ajouter une liste de mots
    Par patch2007 dans le forum Word
    Réponses: 2
    Dernier message: 23/12/2013, 09h13
  5. 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

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