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 :

trier gros dictionnaire de liste [Python 3.X]


Sujet :

Python

  1. #1
    Membre éclairé
    Homme Profil pro
    BTS SN IR
    Inscrit en
    Mai 2017
    Messages
    513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : BTS SN IR

    Informations forums :
    Inscription : Mai 2017
    Messages : 513
    Points : 700
    Points
    700
    Par défaut trier gros dictionnaire de liste
    Bonjour,
    j'avais des fichiers de 500 lignes chacun de la forme item:quantité et une boucle for:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    for line in file:
    	try:
    		dict[line.split(":")[0]] += int(line.split(":")[1]).rstrip("\n")
    	except:
    		dict[line.split(":")[0]] = int(line.split(":")[1]).rstrip("\n")
    par exemple avec un fichier comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    voiture:2
    camion:4
    voiture:3
    dict = {'voiture' : 5, 'camion' : 4}

    Cependant maintenant j'ai des fichiers toujours de 500 lignes mais de la forme item:quantité:catégorie et il faut que je puisse trier mon dictionnaire en fonction de catégorie ...

    J'ai pensé à un dictionnaire de liste
    dict = {'item' : [quantité:"catégorie"]}
    pour additionner les quantités dans la liste sa devrait aller mais pour trier ce dictionnaire une fois la lecture des fichiers fini en fonction de la 2ème valeur de la liste j'ai peur que se soit une vraie usine à gaz :'( (je précise que les catégories ne sont pas connu à l'avance et sont en grand nombre)
    si quelqu'un à une méthode alternative (ou un moyen optimisé de faire ça) je suis tout ouïe pour des conseils.
    Merci d'avance

  2. #2
    Membre émérite

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Points : 2 328
    Points
    2 328
    Par défaut
    A priori ton dictionnaire ressemble plutot à
    dict = {'item' : [quantité, "catégorie"]}
    qu'à
    dict = {'item' : [quantité:"catégorie"]}
    qui n'est pas une écriture valide.

    Ensuite trier un dictionnaire au sens propre du terme ca ne se fait pas. Par définition un dictionnaire n'a pas d'ordre !

    Extrait de la doc disponible ici : https://docs.python.org/2/tutorial/d...l#dictionaries

    The keys() method of a dictionary object returns a list of all the keys used in the dictionary, in arbitrary order (if you want it sorted, just apply the sorted() function to it).
    Ceci dit, il y a une structure de dictionnaire ordonnée nommée OrderedDict (il faut importer collections).
    Tu peux regarder ici, un exemple d'utilisation où un OrderedDict est créé à partir d'un tri sur un dict classique :

    https://docs.python.org/dev/library/...es-and-recipes

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par flapili Voir le message
    J'ai pensé à un dictionnaire de liste
    dict = {'item' : [quantité:"catégorie"]}
    pour additionner les quantités dans la liste sa devrait aller mais pour trier ce dictionnaire une fois la lecture des fichiers fini en fonction de la 2ème valeur de la liste j'ai peur que se soit une vraie usine à gaz
    Il suffit de parcourir les différents éléments du dictionnaire pour fabriquer un dictionnaire "catégories" suivant le même principe avec lequel vous triez les différentes lignes lues pour additionner les différentes occurrences de "camion", "voiture",..?
    La différence est que vous ne lisez plus des lignes mais une entrée (clef, valeur) du dictionnaire juste créé.
    Vous pourriez aussi construire ce dictionnaire là en même temps que l'autre.

    Une autre option serait de lire le fichier de la forme item:quantité:catégorie pour construire une liste de tuples (item, quantité, catégorie) et de construire les différents dictionnaires (qui réalisent les sommes suivant "item" ou "catégorie" ensuite).

    si quelqu'un à une méthode alternative (ou un moyen optimisé de faire ça) je suis tout ouïe pour des conseils.
    pandas saurait faire çà plus simplement mais c'est peut être une bien grosse massue pour de si petites mouches.

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

  4. #4
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    salut,

    est-ce qu'il ne serait pas plus judicieux d'avoir un dictionnaire de dictionnaires {item1:{cat1:val1, cat2:val2}} ?

    on peut ensuite facilement adresser un item-catégorie dico[item][categorie], et quand bien même on ne connait pas toutes les catégories pour chaque item il est facile de les lister avec dico[item].keys() par exemple

    perso je ferais probablement un truc comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    dico = {}
    with open('fichier', 'r') as f:
       for line in f:
          i,v,c = line.rstrip().split(':')
          dico[i] = dico.get(i, {c:0})
          dico[i][c] = dico[i].get(c, 0) + int(v)
     
    from pprint import pprint; pprint (dico)
    et le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ cat fichier
    voiture:2:berline
    camion:4:camion
    voiture:3:sport
    voiture:5:berline
    $ python script.py
    {'camion': {'camion': 4}, 'voiture': {'berline': 7, 'sport': 3}}

  5. #5
    Membre confirmé

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    Une autre solution serait de stocker tout ça dans une bdd sqlite3, ça faciliterait sans doute la manipulation et tris des données.

    En partant du format donné, ça pourrait ressembler à :

    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
    import sqlite3
    import os
     
    BDD = './inventaire.db'
     
    creerBDD = not os.path.isfile(BDD)
    connexion = sqlite3.connect(BDD)
    cur = connexion.cursor()
     
    if creerBDD :
        cur.execute(
            '''CREATE TABLE CATEGORIES(
                cat_id INTEGER PRIMARY KEY AUTOINCREMENT,
                cat_nom TEXT UNIQUE NOT NULL)'''
        )
     
        cur.execute(
            '''CREATE TABLE ITEMS(
                item_id INTEGER PRIMARY KEY AUTOINCREMENT,
                cat_id INT,
                item_nom TEXT,
                item_quantite INT,
                FOREIGN KEY(cat_id) REFERENCES CATEGORIES(cat_id))'''
        )
        connexion.commit()
     
        with open('fichier', 'r') as f :
            for line in f :
                item, quantite, cat = line.rstrip().split(':')
                try :
                    cur.execute(
                        'INSERT INTO CATEGORIES(cat_nom) VALUES(?)',
                        (cat,)
                    )
                    catId = cur.lastrowid
                # La catégorie existe déjà (unique)
                except sqlite3.IntegrityError :
                    r = cur.execute('SELECT cat_id FROM CATEGORIES WHERE cat_nom=?', (cat,))
                    catId = r.fetchone()[0]
                cur.execute(
                    'INSERT INTO ITEMS(cat_id, item_nom, item_quantite) VALUES(?, ?, ?)',
                    (catId, item, quantite,)
                )
            connexion.commit()
    Ceci effectué, il ne reste plus qu'à faire un simple select à la suite :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    req = '''SELECT cat_nom, item_nom, item_quantite FROM ITEMS
    INNER JOIN CATEGORIES USING(cat_id)
    ORDER BY cat_nom, item_nom'''
     
    for l in cur.execute(req) :
        print('catégorie :', l[0], ', item :', l[1], ', quantité :', l[2])
     
    connexion.close()
    Tu peux également utiliser l'incrémentation de la quantité en cas de doublons au lieu d'insertion, voir les « on duplictae key » et le « unique »

    Bon, faut se plonger un peu dans la doc de sqlite3 et sql en général, mais une simple recherche aboutit facilement avec pleins d'exemples à la clef.
    Et mine de rien le sql, c'est quand même bien d'en acquérir quelques bases, ça servira toujours un jour ^^

    Après comme a dit le gourou du python, c'est peut-être une trop grosse massue pour un si faible besoin.
    Le temps ronge l'amour comme l'acide.

  6. #6
    Membre éclairé
    Homme Profil pro
    BTS SN IR
    Inscrit en
    Mai 2017
    Messages
    513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : BTS SN IR

    Informations forums :
    Inscription : Mai 2017
    Messages : 513
    Points : 700
    Points
    700
    Par défaut
    Bonjour,
    Je me suis inspiré du code de BufferBob
    dico = {}
    with open('fichier', 'r') as f:
    for line in f:
    i,v,c = line.rstrip().split(':')
    dico[i] = dico.get(i, {c:0})
    dico[i][c] = dico[i].get(c, 0) + int(v)

    from pprint import pprint; pprint (dico)
    pour produire ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    with open(os.path.join(BASE_DIR, self.combobox_categorie.currentText(), self.combobox_Item.currentText()), "r", encoding="utf-8") as file:
    	for line in file:
    		item, quantite, categorie = line.rstrip().split(':')
    		self.dico[categorie] = self.dico.get(categorie, {item:0})
    		self.dico[categorie][item] = self.dico[categorie].get(item, 0) + int(quantite)
    et plus loin dans mon code j'ai une fonction qui me permet de "trier" en fonction des catégories (trier dans le sens ou avant dans mes fichiers j'avais pas de catégorie):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for categorie, contenu in self.dico.items():
    	file.write("\n"+ categorie)
    	for key, value in contenu.items():
    		file.write(key + " : " + str(value))
    Merci à tous pour votre aide même si, en me relisant j'ai été très flou (je devait être plus fatigué que je le pensait hier soir visiblement )
    quand je vois que j'ai écrit "dictionnaire de liste" alors je voulais dire "liste de dictionnaire" je me dit que j'aurais mieux fait de mettre le Pc en veille et de me relire le lendemain ..

    Désolé de ne pas avoir été capable d'énoncer mon problème clairement, est t'il possible d'éditer le titre du sujet puisque visiblement mon problème était de créer un dictionnaire de dictionnaire à partir d'un fichier.

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

Discussions similaires

  1. Réponses: 11
    Dernier message: 28/06/2010, 11h16
  2. Réponses: 28
    Dernier message: 24/05/2006, 18h20
  3. [JSP] Trier par date une liste de fichier en JSP
    Par Total dans le forum Servlets/JSP
    Réponses: 10
    Dernier message: 21/02/2006, 15h38
  4. Problème "for" dans dictionnaire de liste
    Par Sayrus dans le forum Général Python
    Réponses: 3
    Dernier message: 15/02/2006, 16h35
  5. Trier une Zone de liste
    Par smicky77 dans le forum Access
    Réponses: 10
    Dernier message: 29/08/2005, 18h40

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