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 :

opérations sur listes et dictionnaires


Sujet :

Python

  1. #1
    Membre à l'essai
    Inscrit en
    Août 2010
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 27
    Points : 16
    Points
    16
    Par défaut opérations sur listes et dictionnaires
    Bonjour à tous, je débute depuis peu sur Python et j'ai un problème pour traiter des listes et dictionnaires.

    Voici le topo:
    j'ai un dictionnaire avec 2 clés :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    d={'Ei' : des_valeurs , 'id': des_identifiants}
    Certains identifiants sont identiques et j'aimerai faire une boucle qui passe tous les éléments de 'id'. Tant que les id sont identiques il faudrait mettre leur valeur (récupérée dans 'Ei' avec l'indice) dans une liste.
    Lorsque tous les id identiques sont dans la liste, on fait la moyenne de leur valeur Ei
    Une fois ceci fait il faudrait repartir sur une seconde série de id identiques

    Un exemple pour être plus clair :p :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    d= {'Ei': 1,3,4,4,6 , 'id' : 'r','r','t','t','t'}
    Ce que j'aimerai c'est passer id, prendre tous les 'r' et mettre leur valeur Ei dans une liste temporaire v:
    ensuite je fais un traitement sur v (moyenne) et après on repart sur le reste des id:
    tous les 't':
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    v=[]
    v.append(4,4,6)...
    j'ai essayé avec de boucles while ou avec un for mais je n'arrive pas à m'en sortir. Même chose quand j'essaye
    ca m'embarque dans des trcus que je n'arrive pas à finaliser


    Merci et j'espère avoir été a peu près clair

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Points : 1 913
    Points
    1 913
    Par défaut
    Avec quelle version de python travailles-tu?
    Chez moi (2.6) la ligne:
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    d= {'Ei': 1,3,4,4,6 , 'id' : 'r','r','t','t','t'}
    ne passe pas.
    par contre:
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    d= {'Ei': (1,3,4,4,6) , 'id' : ('r','r','t','t','t')}
    est admise
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  3. #3
    Membre à l'essai
    Inscrit en
    Août 2010
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 27
    Points : 16
    Points
    16
    Par défaut
    Bonjour,

    oui oui tu as raison c'est moi qui est oublié les parenthèses ! Sorry
    (je suis aussi en 2.6)

    Mis à part ça est ce que ce que j'ai raconté est compréhensible ?

    merci

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Points : 1 913
    Points
    1 913
    Par défaut
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    d= {'Ei': (1,3,4,4,6) , 'id' : ('r','r','t','t','t')}
    L=[(d['id'][i],d['Ei'][i]) for i in xrange(0,len(d['Ei']))]
    R=[(x,[y[1] for y in L if y[0]==x]) for x in set(d['id']) ]
    print R
    résultat:
    [('r', [1, 3]), ('t', [4, 4, 6])]
    Is that what you want ?
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  5. #5
    Membre à l'essai
    Inscrit en
    Août 2010
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 27
    Points : 16
    Points
    16
    Par défaut
    whaooooo ... les bras m'en tombent !
    C'est beau ca !

    Je le teste et je reviens te dire si ca fonctionne avec tout mon jeu de données.

    merci en tous cas !

  6. #6
    Membre éclairé
    Profil pro
    Ingénieur sécurité
    Inscrit en
    Février 2007
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Points : 751
    Points
    751
    Par défaut
    Une version avec le module itertools:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    from itertools import groupby
     
    d = {'Ei': (1,3,4,4,6) , 'id' : ('r','r','t','t','t')}
     
    result = []
    # Retourne les éléments associés à 'r' et à 't'
    for key, group in groupby(zip(d['id'], d['Ei']), lambda x: x[0]):
           # Pour 'r' et 't' on ajoute les éléments retourner par le groupage
           result .append((key, [thing[1] for thing in group]))
     
    print result
    Pas sur que cette solution apporte grand chose de plus, mias ça m'a fait réviser itertools...

  7. #7
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut
    Zavonen, ta solution présente deux inconvénients:


    - perte de l’ordre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    d= {'Ei': (1,3,22,40,40,60,4000,5000) ,
        'id' : ('r','r','x','t','t','t','a','a')}
    L=zip(d['id'],d['Ei'])
    R=[(x,[y[1] for y in L if y[0]==x]) for x in set(d['id']) ]
    print 'R =',R
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    R = [('a', [4000, 5000]), ('x', [22]), ('r', [1, 3]), ('t', [40, 40, 60])]

    - mélange de toutes les occurences dans d[’id’], même non contigues:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    d= {'Ei': (1,3,40,40,60,700,900,3000) ,
        'id' : ('riz','riz','t','t','t','riz','riz','a')}
    L=zip(d['id'],d['Ei'])
    R=[(x,[y[1] for y in L if y[0]==x]) for x in set(d['id']) ]
    print 'R =',R
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    R = [('a', [3000]), ('riz', [1, 3, 700, 900]), ('t', [40, 40, 60])]


    Mais ça n’a peut être pas d’importance pour l’application de rom44.








    J’ai d’abord pensé aussi à groupby(iterable[, key]) , mais sans utliser key égale à lambda x: x[0] je ne suis arrivé à rien.

    J’ai donc écrit une fonction génératrice:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    def f_moy(d):
        jprec,idprec = 0,d['id'][0]
        for j,idx in enumerate(d['id']):
            if idx!=idprec:
                y = idprec,sum(d['Ei'][jprec:j])/(j-jprec)
                jprec,idprec = j,idx
                yield y
        j+=1
        yield d['id'][-1],sum(d['Ei'][jprec:j])/(j-jprec)


    Cette fonction donne les moyennes, puisque c’est ce que vise rom44.





    --------------------------------------------------



    Ta solution est concise, datah, surtout si on l’écrit sous forme de list comprehension.
    Mais elle a deux inconvénients:


    1) elle est plus lente:

    Pour comparer , j’ai réécrit ma fonction pour qu’elle donne les groupes.


    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
    29
    30
    31
    32
    33
    34
    35
    36
    from time import clock
    from itertools import groupby
     
    d = {'Ei': (1,3,4,4,6,70,80,2000,3000,4000,6000,1111,2222,
                23,13,43,53,63,733,93,83,13,33,65,75,85) ,
         'id' : ('r','r','t','t','t','r','r','b','b','b','b','x','y',
                 'a','a','a','a','a','a','a','a','a','a','r','r','r')}
     
    t0 = clock()
    for x in xrange(10000):
        result = [ (key, [thing[1] for thing in group])
                 for key, group in groupby(zip(d['id'], d['Ei']), lambda x: x[0]) ]
    dt = clock()-t0
    print dt
    print result
     
    print '\n'
     
     
    def f_group(d):
        jprec,idprec = 0,d['id'][0]
        for j,idx in enumerate(d['id']):
            if idx!=idprec:
                y = idprec,d['Ei'][jprec:j]
                jprec,idprec = j,idx
                yield y
        j+=1
        yield d['id'][-1],d['Ei'][jprec:j]
     
     
    t0 = clock()
    for x in xrange(10000):
        resf = f_group(d)
    dt = clock()-t0
    print dt
    print [u for u in f_group(d)]
    Résultat: la version avec groupby() prend 27 fois le temps de la fonction f_group().




    2) groupby() renvoit un itérateur qui débite des éléments (k,group) dont group est lui même un itérateur.

    Or si on fait sum(group) , on épuise l’itérateur, c’est à dire que len(group) ne donnera ensuite pas de valeur. Ce qui n’est pas pratique pour calculer la moyenne de chaque groupe, qui est le centre d’intérêt de rom44.

    Pour pallier à cette insuffisance, il faut enregistrer l’objet list(group) ou tuple(group). De ce fait on ne peut plus utiliser une list comprehension.


    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    from time import clock
    from itertools import groupby
     
    d = {'Ei': (1,3,4,4,6,70,80,2000,3000,4000,6000,1111,2222,
                23,13,43,53,63,733,93,83,13,33,65,75,85) ,
         'id' : ('r','r','t','t','t','r','r','b','b','b','b','x','y',
                 'a','a','a','a','a','a','a','a','a','a','r','r','r')}
     
    to = clock()
    for x in xrange(10000):
        result = []
        # Retourne les éléments associés à 'r' et à 't'
        for key, group in groupby(zip(d['id'], d['Ei']), lambda x: x[0]):
               # Pour 'r' et 't' on ajoute les éléments retourner par le groupage
               gr = tuple(group)
               result.append((key, sum(thing[1] for thing in gr)/len(gr)))
    dt = clock()-t0
    print dt
    print result
     
    print '\n'
     
     
    def f_moy(d):
        jprec,idprec = 0,d['id'][0]
        for j,idx in enumerate(d['id']):
            if idx!=idprec:
                y = idprec,sum(d['Ei'][jprec:j])/(j-jprec)
                jprec,idprec = j,idx
                yield y
        j+=1
        yield d['id'][-1],sum(d['Ei'][jprec:j])/(j-jprec)
     
    t0 = clock()
    for x in xrange(10000):
        resf = f_moy(d)
    dt = clock()-t0
    print dt
    print [u for u in f_moy(d)]
    Ce faisant, le temps d’exécution de la méthode avec groupby() augmente: il est multiplié par 2,5 tandis que la méthode avec la fonction génératrice f_moy() voit son temps augmenter d’à peine 1 ou 2 %.

    Ce qui au final fait qe la méthode avec groupby() et renvoi des moyennes met 65 fois plus de temps que la fonction f_moy().

  8. #8
    Membre éclairé
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Points : 773
    Points
    773
    Par défaut
    Hmmm... tu débutes... en python, ou en programmation ?
    Parce que je me suis fais la réflexion suivante : peut être la réalisation du dictionnaire peut être revue pour êter bien plus facile d'emploi, à savoir que les clé de ce dernier serait les identifiants, et ses valeur des listes contenant les valeurs associées à ces derniers :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #une fois formé le dico ressemblerait à ça :
    id={ 'r':[1,3],
         't':[4,4,6]}
    #Basé sur ton exemple :
    #d= {'Ei': 1,3,4,4,6 , 'id' : 'r','r','t','t','t'}
    Cette forme serait bien plus pratique pour pouvoir extraire une moyenne des valeur associées aux identifiants identiques...

    Dans l'hypothèse où tu décide de revoir la conception de ton dico en ce sens, tu peux proceder de plusieur façons pour obtenir ce résultat, l'une d'elle, la plus simple à comprendre pour un débutant en prog : passer par une fonction:
    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
    >>> id={}
    >>> def populate(dico, key, val):
    	if key not in dico:
    		dico[key]=[val]
    	else:
    		dico[key].append(val)
     
     
    >>> populate(id, 'r', 1)
    >>> populate(id, 'r', 3)
    >>> populate(id, 't', 4)
    >>> populate(id, 't', 4)
    >>> populate(id, 't', 6)
    >>> id
    {'r': [1, 3], 't': [4, 4, 6]}
    >>> def moyenne(l):
    	return sum(l)/float(len(l))
     
    >>> moyenne(id['r'])
    2.0
    >>> moyenne(id['t'])
    4.666666666666667
    ou bien une autre façon encore, consiste à passer par une classe, ce qui te permetterait de profiter des mécanismes des méthodes spéciales de celles-ci:
    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
    >>> class Dict(dict):
    	def __init__(s):
    		dict.__init__(s)
    	def __getitem__(s, key):
    		return dict.__getitem__(s,key)
    	def __setitem__(s, key, val):
    		if key in s:
    			dict.__getitem__(s,key).append(val)
    		else:
    			dict.__setitem__(s,key,[])
    			dict.__getitem__(s,key).append(val)
    	def moyenne(s,key):
    		return sum(dict.__getitem__(s,key))/float(len(dict.__getitem__(s,key)))
     
     
    >>> id=Dict()
    >>> id['r']=1
    >>> id['r']=3
    >>> id['t']=4
    >>> id['t']=4
    >>> id['t']=6
    >>> id
    {'r': [1, 3], 't': [4, 4, 6]}
    >>> id.moyenne('t')
    4.666666666666667
    EDIT: Tiens, je me suis dit que si tu avais besoin de garder une trace de l'ordre dans lequel les éléments ont été ajouté au dico, ceci fonctionnerait bien :
    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    >>> class Dict(dict):
    	def __init__(s):
    		s.key_record=[]
    		dict.__init__(s)
    	def __getitem__(s, key):
    		return dict.__getitem__(s,key)
    	def __setitem__(s, key, val):
    		if key in s:
    			dict.__getitem__(s,key).append(val)
    		else:
    			dict.__setitem__(s,key,[])
    			dict.__getitem__(s,key).append(val)
    		s.key_record.append(key)
    	def moyenne(s,key):
    		return sum(dict.__getitem__(s,key))/float(len(dict.__getitem__(s,key)))
    	def get_record(s):
    		trace={}
    		for key in s.key_record:
    			if key not in trace:
    				trace[key]=iter(s[key])
    			yield key,trace[key].next()
     
     
    >>> id=Dict()
    >>> id['r']=1
    >>> id['t']=4
    >>> id['t']=6
    >>> id['r']=3
    >>> id['t']=6
    >>> id
    {'r': [1, 3], 't': [4, 6, 6]}
    >>> for key, val in id.get_record():
    	print key, val
     
     
    r 1
    t 4
    t 6
    r 3
    t 6

  9. #9
    Membre à l'essai
    Inscrit en
    Août 2010
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 27
    Points : 16
    Points
    16
    Par défaut
    whaa merci à dahtah et eyquem pour toutes ces réponses !

    la solution d'eyquem me parait intéressante puisqu'elle semble rapide et permet en plus de conserver les ordres, ce qui pourra m'être utile.
    J'ai quand même une question : quel est le principe/avantage de créer une fonction génératrice ? ce qui ce fait par le yield si j'ai bien compris

    N.tox, en fait je débute dans la programmation par python
    Merci pour tes suggestions mais le dictionnaire ne dépend pas de moi, je récupère les données sous cette forme.

    ++

  10. #10
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut
    Oui, une fonction génératrice est une fonction qui comporte au moins un yield.
    Il ne peut pas y avoir de return dans une fonction génératrice.




    Le principe d’une fonction génératrice, c’est que, lorsque le déroulement du programme arrive sur un yield:
    - le déroulement stoppe sa progression dans la fonction génératrice
    - tous les objets créés au sein de la fonction restent en vie avec leur valeur au moment de la rencontre du yield
    - la valeur de l’objet indiqué par le yield est renvoyé vers l’extérieur de la fonction
    - le déroulement du programme continue à l’extérieur juste après l’instruction qui avait fait un appel à la fonction génératrice.

    Puis pendant que le déroulement continue sa progression à l’extérieur de la fonction génératrice, tout l’espace de noms à l’intérieur de la fonction génératrice persiste (c’est ce qui maintient les objets en vie à l’intérieur de la fonction génératrice).

    Et lorsque le déroulement du programme rencontre un nouvel appel à la fonction génératrice, il y rerentre et y poursuit sa progression. Mais, c’est là le point crucial, le déroulement reprend dans la fonction génératrice à partir exactement du même point précis d’où il était sorti de la fonction:
    c’est à dire que le déroulement reprend non seulement avec les mêmes valeurs des objets internes à la fonction génératrice qui avaient été figées, mais sans refaire le parcours dans la fonction à partir de son début.
    C’est crucial parce que dans le cas de f_moy() par exemple , c’est ce qui fait que jprec et idprec ne reprennent pas les valeurs 0 et d['id'][0] , car l’instruction jprec,idprec = 0,d['id'][0] qui est au début de la fonction n’est exécutée qu’une seule fois, lors du premier appel de f_moy() , et non pas les fois suivantes car la réentrée du déroulement se fait juste après le yield y c’est à dire avec un nouveau tour de la boucle for j,idx in enumerate(d['id']): et non pas à la première instruction.
    Alors que dans le cas d’une fonction normale, le bloc de code de la fonction est exécuté, à chaque appel de la fonction, à partir de son début.


    Il faut noter qu’il peut y avoir plusieurs yield dans le code interne d’une fonction. Les sorties et réentrées du déroulement se feront alors à des endroits différents à l’intérieur de la fonction génératrice selon le yield qui provoque un envoi vers l’extérieur et une sortie.







    Y a-t-il un avantage à recourir à une fonction génératrice pour ton problème ?
    Je n’en ai pas l’impression.

    J’étais parti dans l’écriture du code avec l’idée d’obtenir la liste des résultats (élément de d[’id’] répété , moyenne des d[’Ei’] associés) par une list comprehension.
    L’itération dans la liste comprehension devant se faire par un parcours de d[’id’] , mais avec des traitements compliqués tenant compte pour chaque élément de ce qui a été précédemment rencontré, une fonction génératrice s’imposait.

    Mais il est vrai qu’une list comprehension et la fonction génératrice corrélative ne sont pas du tout obligatoires. Je me suis même aperçu en mesurant les temps d’exécution que le code sans list comprehension est plus rapide: bien qu’il y ait des append() à faire , c’est au total moins long que les appels réitérés à la fonction génératrice dans une list comprehension.




    Au passage, je me suis aperçu que le code de f_moy() a deux lignes superflues.

    Compte tenu de ce que j’ai expliqué plus haut, il n’est pas nécessaire de mettre un identifiant sur idprec,sum(d['Ei'][jprec:j])/(j-jprec) avant de changer jprec et idprec et faire yield.
    Faire disparaître cette ligne d’assignation diminue le temps d’exécution de 1,7 % (cf fonction f_moy_2() )

    La solution avec une fonction normale f_moy_R() (avec return) prend 5,5 % de temps en moins que f_moy_2()
    Conclusions basées sur les temps minimaux observés sur une cinquantaine d’essais.

    Par ailleurs, pas besoin de j+=1 en avant-dernière instruction.



    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    from time import clock
     
    def f_moy(d):
        jprec,idprec = 0,d['id'][0]
        for j,idx in enumerate(d['id']):
            if idx!=idprec:
                y = idprec,sum(d['Ei'][jprec:j])/(j-jprec)
                jprec,idprec = j,idx
                yield y
        yield d['id'][-1],sum(d['Ei'][jprec:])/(j+1-jprec)
     
    def f_moy_2(d):
        jprec,idprec = 0,d['id'][0]
        for j,idx in enumerate(d['id']):
            if idx!=idprec:
                yield idprec,sum(d['Ei'][jprec:j])/(j-jprec)
                jprec,idprec = j,idx
        yield d['id'][-1],sum(d['Ei'][jprec:])/(j+1-jprec)
     
    def f_moy_R(d):
        lires = []
        jprec,idprec = 0,d['id'][0]
        for j,idx in enumerate(d['id']):
            if idx!=idprec:
                lires.append((idprec,sum(d['Ei'][jprec:j])/(j-jprec)))
                jprec,idprec = j,idx
        lires.append((d['id'][-1],sum(d['Ei'][jprec:])/(j+1-jprec)))
        return lires
     
     
     
    d = {'Ei': (1,3,4,4,6,70,80,2000,3000,4000,6000,1111,2222,
                23,13,43,53,63,733,93,83,13,33,65,75,85) ,
         'id' : ('r','r','t','t','t','r','r','b','b','b','b','x','y',
                 'a','a','a','a','a','a','a','a','a','a','r','r','r')}
     
    A,B,C = [],[],[]
     
    for mesure in xrange(5):
        t0 = clock()
        for i in xrange(1000):
            x = [ u for u in f_moy(d) ]
        dt = clock()-t0
        A.append(dt)
     
        t0 = clock()
        for i in xrange(1000):
            y = [ u for u in f_moy_2(d) ]
        dt = clock()-t0
        B.append(dt)
     
        t0 = clock()
        for i in xrange(1000):
            z = f_moy_R(d)
        dt = clock()-t0
        C.append(dt)
     
    print x==y==z
    print min(A),'\n',min(B),'\n',min(C)
    .

  11. #11
    Membre à l'essai
    Inscrit en
    Août 2010
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 27
    Points : 16
    Points
    16
    Par défaut
    ok merci pour toutes ces explications et surtout tous ces tests ! je suis impressionné

    dernière question : quelle différence y a t-il entre une list et une list compréhension ?

  12. #12
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut
    Une liste est un objet du genre structure de données.



    Une list comprehension est une expression qui construit une liste selon une méthode que je ne connais pas mais qui est en général plus rapide.
    Ce n’est pas toujours vrai: c’est le cas observé sur ton problème tel que je l’ai traité avec une fonction génératrice.

    Mais une list comprehension est toujours plus condensée: écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    li = [ traitement_de(u) for u in conteneur if condition_sur(u) ]
    est plus court que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    li = []
    for u in conteneur:
        if condition_sur(u):
            li.append(traitement_de(u))
    Il doit y avoir des tonnes de renseignements sur les list comprehension sur internet.

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Points : 1 913
    Points
    1 913
    Par défaut
    Le terme anglo-américain 'list-comprehension' est d'ailleurs pour moi un mystère absolu car contraire aux usages de formation des mots dans cette langue. En effet les qualificatifs et les déterminants du substantif sont toujours plaçés AVANT le substantif qu'ils déterminent. Or une 'list comprehension' est avant tout une liste fabriquée par une itération sous-jacente en quelque sorte déguisée. Donc en tout état de cause le vocable anglais devrait être 'comprehension defined list' pouvant s'abréger en 'comprehension list'. Cela correspond, l'ordre en moins, dans la langue de Molière, à un "ensemble défini en compréhension" (ex: l'ensemble des nombres pairs dont le carré n'excède pas 30).
    Finalement je me demande si une fois de plus on ne doit pas cela à des informaticiens n'ayant que des connaissances très vagues des mathématiques et ou de la syntaxe de la langue anglaise. Après tout le BDFL est batave, non?
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  14. #14
    Membre expérimenté
    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
    Points : 1 384
    Points
    1 384
    Par défaut
    Je ne pense pas que ce soit du mauvais anglais. Ce terme n'est pas utilisé qu'en Python; la plupart des langages offrant cette possibilité l'appellent ainsi. Le terme "set comprehension" est utilisé en mathématiques pour "ensemble défini par compréhension". "list comprehension" dérive de là.

    "compréhension de liste" est sans doute une mauvaise traduction française, mais l'idée est là. Le substantif est "comprehension", pas "list". Cela désigne la syntaxe utilisée, pas l'objet produit.

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Points : 1 913
    Points
    1 913
    Par défaut
    Le substantif est "comprehension", pas "list". Cela désigne la syntaxe utilisée, pas l'objet produit.
    C'est bon à savoir, merci pour ton apport, Dividee.
    Je mourrai moins c...
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  16. #16
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut
    J’avais un doute sur ce que je devais écrire, je me disais que je devrais logiquement écrire "comprehension list" car je suis du même avis que Zavonen, mais j’avais l’impression que ce n’était pas ce qui était employé généralement. J’ai décidé de ne pas vérifier et de laisser le problème en suspens pour cette fois.

    Je vois que le vocabulaire vous importe aussi, dans un souci de rigueur, y compris Zavonen. Je ne peux qu’acquiescer.





    Le substantif est "comprehension", pas "list".
    Dans ce cas, ma phrase suivante est juste:
    Une list comprehension est une expression
    Mais je n’ai pas fait exprès.



    Cependant je ne suis pas entièrement d’accord: il y a des cas où on, où je en tous cas, désigne par cette tournure une liste, c’est à dire le résultat obtenu par une expression syntactique de type list comprehension. Ce serait donc erroné dans ce cas, et on devrait dire comprehension list ?





    "compréhension de liste" est sans doute une mauvaise traduction française
    Notez que pour wikipedia:

    Une liste, comme un ensemble, peut-être définie par la donnée d'une propriété caractéristique de ses éléments, on dit qu'on l'a définie en compréhension. Comme cette construction offre des avantages de lisibilité et de concision, certains langages de programmation proposent donc la possibilité de définir une liste par une propriété caractéristique et l'on appelle cela la compréhension de liste.

    http://fr.wikipedia.org/wiki/Compr%C...nsion_de_liste


    Pour ma part, je pense qu’il y a une ambiguité qui persiste parce que quoiqu’on fasse, le terme compréhension dans "définir une liste en compréhension" désigne la MÉTHODE de définition.
    Tandis que list comprehension est censée désigner une EXPRESSION SYNTACTIQUE.

    Quoi qu’on dise, une méthode n’est pas l’écriture, sauf par métonymie. Or les métonymies sont pénibles quand on veut être rigoureux.

    Wikipedia évite habilement de se mouiller:
    on appelle cela la compréhension de liste
    "cela" c’est quoi ?



    Le problème reste ouvert , et moi semblablement c..

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Points : 1 913
    Points
    1 913
    Par défaut let's dig a little bit more
    Cette affaire me turlupine.
    Dans mon souvenir 'compréhension' se disait plutôt dans la langue de Shakespeare 'understanding'. D'où mon idée de prendre le taureau par les cornes et de retourner au dictionnaire. Souvent les anglais ont deux mots pour une même notion une d'origine saxone et une d'origine latine, mais en général avec une variation de sens (ex classique liberty // freedom). Ici nous sommes en plein dans ce cas. Nous avons le mot 'latin' (cum-prehendere : prendre avec) et le mot saxon (understanding : se situer au dessous).
    Si les anglais étaient des gens comme nous cela se saurait... La version 'latine' qui est donc la même pour nous et pour eux est logique, comprendre : c'est 'prendre avec', assimiler une nouvelle connaissance pour qu'elle s'intègre avec l'acquis. Mais il y a le second sens: "L'ensemble des nombres premiers comprend le nombre 3". Il n'est pas ici question de compréhension intellectuelle mais simplement de contenance. Or nous en français nous avons perdu le substantif lié à ce verbe, on ne dit plus si on n'a jamais dit "la compréhension de 3 dans l'ensemble des nombres premiers". Les anglais eux l'ont conservé, comme le montre le lien ci-dessus.
    http://www.thefreedictionary.com/comprehension
    Ainsi on peut comprendre le point de vue exposé par dividee si on prend le second sens du mot comprehension dans l'expression 'list comprehension' comme propriété caractéristique d'appartenance à une liste. Il reste que la traduction est difficile.
    Bien, maintenant il reste à comprendre pourquoi les anglais pigent quand ils se situent 'au dessous' moins je pige quand je survole donc quand je me situe 'au-dessus'.
    Si vous avez des lumières là-dessus, welcome!
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  18. #18
    Futur Membre du Club
    Inscrit en
    Octobre 2010
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 9
    Points : 5
    Points
    5
    Par défaut
    J'ai trouvé très esthétique et efficace la première solution au problème posé, sous forme de "list comprehension".
    Je me suis donc permis de la reprendre dans un billet (http://idl2python.blogspot.com/2010/...rehension.html), en citant la source bien entendu ;-)

  19. #19
    Membre expérimenté
    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
    Points : 1 384
    Points
    1 384
    Par défaut
    Comme StarObs a remonté ce fil, j'en profite pour répondre à Zavonen, dont je n'avais pas vu le post à l'époque.

    "ensemble défini en compréhension" (par opposition à "défini en extension") est encore utilisé en français, à ma connaissance. C'est ce terme qu'on m'a appris à l'école en tout cas.
    Mais pour moi cela ne fait pas référence au second sens du mot comprehension sur le lien que tu donnes, mais au 3ème: "The sum of meanings and corresponding implications inherent in a term."
    Ou en français: http://fr.wikipedia.org/wiki/Compréhension (la section "Logique").

    Quant à "understanding", il semblerait que le préfixe "under" n'ait pas ici le sens "en-dessous". Le sens de "under" viendrait ici du Proto-Indo-Européen "*nter" (qui aurait donné "inter" en latin) et signifie donc plutôt "parmi, entre". On retrouve ce sens de "under" dans l'expression "under these circumstances", qui signifie "dans ces circonstances" et pas "sous ces circonstances".
    cf http://www.etymonline.com/index.php?term=understand
    Donc, l'étymologie de "understand" n'est pas purement anglo-saxonne non plus...

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Points : 1 913
    Points
    1 913
    Par défaut
    Donc, l'étymologie de "understand" n'est pas purement anglo-saxonne non plus...
    Bon, de toutes façons la plupart des langues européennes (pas toutes) anciennes ou contemporaines, ce n'est finalement que du patois de sanscrit.
    Je me suis, en d'autres temps, aussi pas mal intéressé aux préfixes et prépositions dont l'usage est intense en latin, russe, allemand et dont nous avons aussi hérité via le latin. L'anglais a, quant à lui, un double héritage (saxon et latin via le français). Ta remarque, Dividee, concernant 'under' et 'inter' est assez intéressante et résoudrait partiellement une de mes angoisses existentielles. N'empêche que dès que j'ai un moment je vais proposer à nos amis britanniques d'adopter définitivement 'overstand' pour 'piger' car être au milieu, c'est déjà mieux que d'être en dessous, mais c'est moins bien qu'être au-dessus.
    Je vais retrouver le sommeil
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [AC-2013] Opérations sur un champ Liste de choix automatique
    Par frieden dans le forum Requêtes et SQL.
    Réponses: 7
    Dernier message: 04/06/2015, 19h23
  2. opération sur deux listes
    Par simnitch dans le forum Lisp
    Réponses: 7
    Dernier message: 24/04/2013, 10h12
  3. Opérations sur des morceaux de liste
    Par edding4 dans le forum Général Python
    Réponses: 7
    Dernier message: 10/10/2011, 15h47
  4. Opération sur liste
    Par jouclar dans le forum Général Python
    Réponses: 4
    Dernier message: 24/05/2011, 19h17
  5. [langage] random sur liste ou tableau
    Par martijan dans le forum Langage
    Réponses: 2
    Dernier message: 15/07/2003, 14h47

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