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 :

Comparaison des clés d'une liste


Sujet :

Python

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4
    Par défaut Comparaison des clés d'une liste
    Bonjour,

    Je code depuis quelques années en PHP et j'ai commencé python depuis quelques jours.

    Ci-dessous le descriptif du programme à réaliser :

    Vous souhaitez analyser vos revenus et dépenses passés afin de déterminer quels sont les mouvements récurrents chaque mois.

    Pour cela, vous avez extrait tous les mouvements de chacun des derniers mois. Chaque mouvement est composé d'un nom et d'un montant. Un mouvement est considéré comme récurrent s'il est présent dans chaque relevé mensuel (le nom et le montant doivent être identiques chaque mois).

    Attention : Une ou plusieurs des dernières lettres d'un nom peuvent être remplacées par un point. Ces noms doivent alors être considérés comme identiques. Il y a obligatoirement au moins 3 lettres avant le point, il n'y a un seul point possible par nom et il sera toujours situé en fin de nom.

    Par exemple, le nom "salaire" est considéré comme identique aux noms suivants : salair. salai. sala. sal.

    Par contre, il n'est pas considéré comme identique aux noms suivants : sale. (ne commence pas pareil) salaire. (Un point remplace obligatoirement 1 ou plusieurs caractères) sala (pas de point à la fin)

    Les mouvements sont triés par nom (ordre alphabétique) puis par montant croissant (si noms identiques).

    Vous décidez d'écrire un programme qui prend en entrée la liste des mouvements mensuels et renvoie en sortie le nombre de mouvements récurrents chaque mois, ainsi que la somme de ces mouvements.
    Par exemple, si vous avez récupéré les mouvements des 3 derniers mois :

    Mois 1:

    loyer : -485.00 €
    restaurant : -32.50 €
    retrait : -40.00 €
    salaire : 2300.00 €

    Mois 2 :

    loyer : -485.00 €
    remboursement : 45.68 €
    retrait : -60.00 €
    retrait : -30.00 €
    sal. : 2300.00 €
    virement : 700.00 €

    Mois 3 :

    loyer : -485.00 €
    retrait : -40.00 €
    salai. : 2300.00 €

    Votre fonction devra retourner qu'il y a 2 mouvements récurrents (salaire et loyer) et que la somme de ces mouvements est de 1815.00€ (-485 + 2300). "salaire" est considéré comme récurrent car il y a pour chaque mois une des opérations suivantes :

    salaire : 2300.00 €
    sal. : 2300.00 €
    salai. : 2300.00 €

    Programmation Orientée Object appréciée
    Entrée de la fonction

    La 1ère ligne contient un nombre entier N compris entre 1 et 12 inclus, représentant le nombre de mois d'historique que vous allez analyser.

    S'en suivent N lignes contenant les mouvements de chaque mois sous la forme suivante :

    Chaque ligne est composée d'entre 1 et 30 mouvements séparés par un espace.
    Chaque mouvement est composé d'un nom et d'un montant séparés par un point-virgules tels que :
    Le nom du mouvement est composé d'une chaîne de caractères comprenant entre 1 et 30 lettres minuscules et potentiellement 1 point (pas d'espaces ni d'autres caractères de ponctuation que le point, maximum 1 point par chaîne de caractères)
    Le montant du mouvement est sous la forme d'un nombre à 2 décimales compris entre -9999.99 et 9999.99 inclus. Le séparateur décimal est un point et les 2 décimales sont toujours affichées, même si le montant est rond (ex. 800.00).

    Exemple d'une ligne de mois d'historique : salaire;2300.00 loyer;-485.00 retr.;-40.00
    Sortie de la fonction

    Votre fonction doit retourner le nombre de mouvements récurrents ainsi que la somme de ces mouvements, séparés par un point-virgule, tels que :

    Le nombre de mouvements récurrents doit être un nombre entier égal ou supérieur à 0.
    La somme des mouvements doit être un nombre à 2 décimales systématiquement affichées et un point comme séparateur décimal.

    Exemple de sortie: 2;1815.00

    Ci-dessous le bout de programme que j'ai écrit et qui ne marche que dans un cas :

    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
    def main(i, x, y, z):
        #Write your code here ...
        #intersection : Fait l'intersection de 3 ensembles
        #len : retourne la taille du tableau
        nb = len(set(x).intersection(y).intersection(z))
        inter = set(x).intersection(y).intersection(z)
        somme = 0
        #Pour chaque élément du tableau
        for item in inter:
            #scinde un string par le délimiteur indiqué (dans notre cas, c'est un ";") et retourne un tableau d'éléments
            sp = item.split(';')
            #récupère le 2ème élément du tableau
            so = sp[1]
            #on fait la somme
            somme = somme + float(so)
        #on affiche
        print str(nb) + ";" + str(somme)
     
    n = 3
    a = ["loyer;-485.00", "restaurant;-32.50", "retrait;-40.00", "salaire;2300.00"]
    b = ["loyer;-485.00", "remboursement;45.68", "retrait;-60.00", "retrait;-30.00", "salaire;2300.00", "virement;700.00"]
    c = ["loyer;-485.00", "retrait;-40.00", "salaire;2300.00"]  
    main(n, a, b, c)

  2. #2
    Membre expérimenté
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2011
    Messages : 180
    Par défaut
    Bonjour

    Un exercice pas inintéressant et un peu plus difficile qu'il n'y paraît.
    Il est tout à fait normal que, dans ton cas, seul "loyer" sera considéré comme récurrent.
    En effet, les intersection ensemblistes vont se baser sur la valeur de hashage des strings
    composant tes listes. Dés lors sal. n'a pas la même signature que salaire.

    Qui plus est, cette façon de de faire ne fonctionne que le montant associé au loyer reste constant.

    Tu devrais t'arranger pour transformer tes listes de strings en liste d'objet similaires à celui-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
     
    class Mouvement(object):
        def __init__(self,clef,valeur):
            self.clef = clef
            self.valeur = valeur
        def __eq__(self,other):
            eq = self.clef == other.clef
            if not eq:
                x , y = self.clef,other.clef
                if len(y)<len(x):
                    x,y = y,x
                if '.' in x:
                    x = x[:-1]
                    eq = y[:len(x)] == x
            return eq
    Deux instances de la classe Mouvement se compareront à l'identique si et seulement si
    leurs clefs correspondent à la condition que tu énonçais. Même si les montant ne correspondent pas.

    A partir de là, tu peux facilement écrire toi même une fonction d'intersection.

    Bon courage

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4
    Par défaut
    Merci Chticricri pour ton retour,

    J'avoue que c'est beaucoup plus compliqué qu'il n'y parait.
    Je vais essayer de voir ça.

    Si quelqu'un d'autre a une piste pour compléter ce qui a été dit, je suis preneur.

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4
    Par défaut
    N'y aurait-il pas un autre bon samaritain dans le coin ?

  5. #5
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 304
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 304
    Par défaut
    Salut,

    En séparant les tâches, ce n'est plus si compliqué que cela.

    Une base de départ:
    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
    60
    61
    62
    63
    64
    65
    66
    67
    68
     
    # -*- encoding: utf-8 -*-
    class Accountancy(object):
        def __init__(self):
            self.data = {}
     
        def add_values(self, label, values):
            # TODO vérifier que le label n'existe pas déjà
            self.data[label] = {}
            for value in values:
                # TODO prévoir les erreurs d'encodage
                reason, val = value.split(';')
                if reason not in self.data[label]:
                    self.data[label][reason] = [float(val)]
                else:
                    self.data[label][reason].append(float(val))
     
        def normalise_labels(self):
            names = set([])
            replaced = []
            added = []
            for key in self.data.keys():
                for k in self.data[key].keys():
                    if not k.endswith('.'):
                        names.add(k)
     
            for key in self.data.keys():
                for k in self.data[key].keys():
                    if k.endswith('.'):
                        j = k.rstrip('.')
                        for i in names:
                            if i.startswith(j):
                                if i in self.data[key]:
                                    self.data[key][i].extend(self.data[key][k])
                                else:
                                    # On ne modifie pas les clés pendant l'iteration
                                    added.append([key, i, self.data[key][k]])
                                replaced.append([key, k])
     
            # Maintenant on peut modifier les clés
            for k in replaced:
                del self.data[k[0]][k[1]]
     
            for a in added:
                self.data[a[0]][a[1]] = a[2]
     
    class PrintAccount(object):
        def __init__(self, acc):
            self.acc = acc
     
        def print_(self):
            self.acc.normalise_labels()
            data = self.acc.data
            for datum in data:
                print('--- %s -------------------------------' % datum)
                # TODO créer un tableau, formater les nombres, etc.
                print(data[datum])
     
    a = ["loyer;-485.00", "restaurant;-32.50", "retrait;-40.00", "salaire;2300.00"]
    b = ["loyer;-485.00", "remboursement;45.68", "retrait;-60.00", "retr.;-30.00", "salaire;2300.00", "virement;700.00"]
    c = ["loyer;-485.00", "retrait;-40.00", "sal.;2300.00", "restau.;-50.20"]
     
    ac = Accountancy()
    for idx, v in enumerate([a, b, c]):
        ac.add_values("mois-%s" % idx, v)
     
    pa = PrintAccount(ac)
    pa.print_()
    Python 2 et 3

Discussions similaires

  1. récupération des données via une liste déroulante
    Par rahan_dave dans le forum Access
    Réponses: 1
    Dernier message: 13/10/2005, 12h27
  2. [CSS]Changer l'interligne des éléments d'une liste à puces
    Par khany dans le forum Mise en page CSS
    Réponses: 4
    Dernier message: 21/03/2005, 13h57
  3. [Lisp] Suppression des parenthèses dans une liste
    Par bourdaillet dans le forum Lisp
    Réponses: 3
    Dernier message: 19/12/2004, 21h02
  4. [langage] Comment rajouter des champs dans une liste
    Par toto_titi dans le forum Langage
    Réponses: 4
    Dernier message: 28/08/2003, 14h09

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