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

Langage Perl Discussion :

Problème de calculs suite à un changement de données.


Sujet :

Langage Perl

  1. #1
    Membre habitué
    Inscrit en
    Septembre 2005
    Messages
    747
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 747
    Points : 174
    Points
    174
    Par défaut Problème de calculs suite à un changement de données.
    Bonsoir,

    J'ai un tableau qui contient des données de ce type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    my $ref_tab =
    [
      ["25-11-2007",10,20,30,40,50,60,70,80],
      ["26-11-2007",15,25,35,45,55,65,75,85]
    ];
    Les valeurs indiquées dans le tableau correspondent respectivement à une date, le nombre de lettres valides, le nombre de lettres invalides, le nombre de lettres en attente, le nombre de lettres retournées, le nombre de colis valides, le nombre de colis invalides, le nombre de colis en attente et le nombre de colis retournés.

    Ces données sont insérées dans divers tableaux de la façon suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    my (@dates, @lettre_valide, @lettre_invalide, @lettre_attente, @lettre_retourne, @colis_valide, @colis_invalide, @colis_attente, @colis_retourne);
     
    foreach my $line (@ref_tab) {
    	unshift(@dates,    $$line[0]);
    	unshift(@lettre_valide, $$line[1]);
    	unshift(@lettre_invalide, $$line[2]);
    	unshift(@lettre_attente, $$line[3]);
    	unshift(@lettre_retourne, $$line[4]);
    	unshift(@colis_valide,  $$line[5]);
    	unshift(@colis_invalide, $$line[6]);
    	unshift(@colis_attente, $$line[7]);
    	unshift(@colis_retourne,   $$line[8]);
    }
    Les calculs suivant sont effectués :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    my ($total_lettre_valide, $total_lettre_invalide, $total_lettre_attente, $total_lettre_retourne, $total_colis_valide, $total_colis_invalide, $total_colis_attente, $total_colis_retourne) = (0,0,0,0,0,0,0,0);
     
    map { $total_lettre_valide    += $_ } @lettre_valide;
    map { $total_lettre_invalide  += $_ } @lettre_invalide;
    map { $total_lettre_attente   += $_ } @lettre_attente;
    map { $total_lettre_retourne += $_ } @lettre_retourne;
    map { $total_colis_valide      += $_ } @colis_valide;
    map { $total_colis_invalide    += $_ } @colis_invalide;
    map { $total_colis_attente     += $_ } @colis_attente;
    map { $total_colis_retourne   += $_ } @colis_retourne;
    J'aurais besoin d'ajouter de nouveaux moyens d'envois comme le mail par exemple. Pour éviter d'avoir des dizaines de tableaux ou variables à déclarer, il faut donc que je change de modele.

    Le nouveau tableau est de ce type.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    my $ref_tab =
    [
      ["25-11-2007",1,10,20,30,40],
      ["25-11-2007",2,50,60,70,80],
      ["26-11-2007",1,15,25,35,45],
      ["26-11-2007",2,55,65,75,85]
     
    ];
    Le tableau précédent a été décomposé et contient maitenant respectivement : une date, la source d'envois (1 pour lettre, 2 pour colis), le nombre valide suivant la source, le nombre d'invalide suivant la source, le nombre en attente suivant la source et le nombre retourné suivant la source.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    my (@dates, @source, @valide, @invalide, @attente, @retourne);
    #J'ai réussi à remplir, les différents tableaux qui contiennent maitenant :
    @dates = ("25-11-2007","26-11-2007");
    @source = ([1,2],[1,2]);
    @valide = ([10,50],[15,55]);
    @invalide = ([20,60],[25,65]);
    @attente = ([30,70],[35,75]);
    @retourne = ([40,80],[45,85]);
    }
    Le problème que j'ai se situe au niveau du calcul des totaux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my ($total_valide, $total_invalide, $total_attente, $total_retourne) = (0,0,0,0);
    Je ne sais pas comment faire pour retrouver les mêmes valeurs que dans le 1er cas ainsi que la manière de stocker ces données.

    Depuis ce matin, j'essaye mais sans succès.

    Merci d'avance

  2. #2
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Bonjour,

    Je ne suis pas certaine d'avoir tout bien compris.
    A partir de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @dates = ("25-11-2007","26-11-2007");
    @source = ([1,2],[1,2]);
    @valide = ([10,50],[15,55]);
    @invalide = ([20,60],[25,65]);
    @attente = ([30,70],[35,75]);
    @retourne = ([40,80],[45,85]);
    @dates = ("25-11-2007","26-11-2007");
    @source = ([1,2],[1,2]);
    @valide = ([10,50],[15,55]);
    @invalide = ([20,60],[25,65]);
    @attente = ([30,70],[35,75]);
    @retourne = ([40,80],[45,85]);

    Tu veux retrouver les totaux jours confondus?
    $total_valide 10 + 50 + 15 + 55
    $total_invalide 20 + 60 + 25 + 65
    ..

    Allez courage, il y a toujours une solution.

    Voila comment parcourir tes valeurs :
    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
    my ($total_valide, $total_invalide, $total_attente, $total_retourne) = (0,0,0,0);
    my ($total_valide_lettre, $total_valide_colis) = (0,0);
     
    print "Chiffres à additionner : ";
    for (my $array = 0;  $array < @valide; $array++)
    {
            for (my $num = 0;  $num < @{$valide[$array]}; $num++)
            {
                    print $valide[$array][$num]."\t";
                    $total_valide = $total_valide + $valide[$array][$num];
                    if ($source[$array][$num] == 1){$total_valide_lettre = $total_valide_lettre + $valide[$array][$num];}
                    elsif ($source[$array][$num] == 2){$total_valide_colis = $total_valide_colis + $valide[$array][$num];}
            }
    }
     
    print "\n\nTotal valide => ".$total_valide."\n";
    print "Total colis => ".$total_valide_colis."\n";
    print "Total lettres => ".$total_valide_lettre."\n";

    Résultat :
    Chiffres à additionner : 10 50 15 55

    Total valide => 130
    Total colis => 105
    Total lettres => 25

    Jasmine,

  3. #3
    Membre confirmé
    Avatar de Schmorgluck
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    371
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2006
    Messages : 371
    Points : 558
    Points
    558
    Par défaut
    Allez, je me lance.

    La question que je me pose, c'est si ta façon de récupérer les données de ton tableau est vraiment pertinente. Ce que tu cherches à obtenir, au final et si j'ai bien compris, c'est pour chaque date une structure de données contenant les informations sur les divers envois. Puis à faire la somme de tous ces envois, par type d'envoi.
    La façon la plus commode (à ma connaissance tout du moins - j'ai encore des grosses lacunes en ce qui concerne les modules) d'implémenter des structures de données de cet ordre de complexité, est de recourir (encore) aux hachages. Ça peut donner, si c'est bien fait, une robustesse et une souplesse que ne permettent pas les tableaux. Ça permettra aussi d'utiliser un certain nombre de perlismes qui simplifieront et clarifieront pas mal le code.
    Ce qui est intéressant, c'est qu'on a le choix entre plusieurs façons de ranger les données. Ici, je pense, des hachages de hachages de hachages pourraient convenir, mais un hachage de hachages de tableaux me semble plus pertinent (on verra pouquoi tout à l'heure). Il faut aussi décider par quel clé tu souhaites accéder principalement à tes données, donc quelle sera le hachage principal. Je vais garder l'ordre de ton tableau, et faire de la date la clé principale. C'est arbitraire, je ne suis pas certain que ce soit la meilleur solution, j'ai l'intuition que ça ne change pas grand chose, je suis en train d'improviser, là.

    On va commencer par créer un hachage permettant de transformer les codes de types d'envois en chaînes de caractères. Ça nous sera utile pour les clés et les affichages. De plus, on va créer un tableau des statuts dans l'ordre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    my %decode_type=(
    1 => "lettre",
    2 => "colis",
    3 => "mail");
    my @statuts = qw(valide invalide attente retourne);
    Ensuite, on va donc partir de $ref_tab (qui n'a pas vraiment besoin d'être une référence, soit dit en passant, un tableau ordinaire aurait convenu tout autant) et en extraire toutes les données dans un hachage de hachages de tableaux.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #déclaration du hachage qui va contenir tout notre bazar
    my %structure;
    foreach my $ref_entree (@{$ref_tab})
    {
    #premier perlisme, bien pratique je trouve.
        my ($date, $code, @quantites) = @{$ref_entree};
        my $type = $decode_type{$code};
    #j'ai peut-être parlé un peu vite à propos de clarté. Voir perlref ou la FAQ.
    #en tout cas, le fait d'utiliser des hachage nous épargne de fastidieuses déclarations :
        $structure{$date}->{$type}=\@quantites;
    }
    Voilà, si tout va bien, on a un hachage %structure avec la date pour clé, contenant des références vers des hachages avec le type d'envoi pour clés, contenant des références vers des tableaux contenant les quantités dans l'ordre (c'est pour conserver l'ordre initial que je n'ai pas utilisé de hachage à ce niveau).

    Et maintenant, pour obtenir tes totaux :
    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
    #déclaration du hachage qui va contenir les tableaux de totaux par types
    my %totaux;
    # je crois que j'aurais pu écrire ces trois foreach imbriqués sur une seule ligne
    # idée terrifiante, n'est-ce pas ?
    foreach my $date (keys %structure)
    {
        foreach my $type (keys %{$structure{$date}})
        {
    # j'ai préféré utiliser le dernier indice du tableau @statuts, ici, au lieu de
    # mettre 3 en dur, pour des raisons de robustesse
            foreach my $s (0..$#statuts)
            {
                $totaux{$type}->[$s] += $structure{$date}->{$type}->[$s];
            }
        }
    }
    Voilà voilà, et maintenant, si tu veux afficher les résultats, ben, rien de plus simple . Voici une des nombreuses possibilités :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    foreach my $type (sort keys %totaux)
    {
        my @valeurs = @{$totaux{$type}};
        print "$type :\n";
        foreach my $statut (@statuts)
        {
            print "\t$statut : ",shift (@valeurs),"\n";
        }
    }
    Ce qui nous donne pour affichage
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    colis :
            valide : 105
            invalide : 125
            attente : 145
            retourne : 165
    lettre :
            valide : 25
            invalide : 45
            attente : 65
            retourne : 85
    Ce qui me semble bien correspondre à ce que tu voulais.

    Grâces aux hachages, tu peux ajouter autant de codes de types de courriers que tu veux, tu n'auras à changer que le contenu de %decode_type. De même, le tableau @statuts peut être modifié si tes données changent et se retrouvent avoir plus, ou moins, de statuts possibles pour les courriers.

    EDIT: Tiens, j'ai raisonné un brin de travers à propos de la troisième couche : j'aurais très bien pu en faire un hachage aussi, vu que le tableau @statuts est là pour indiquer au programme l'ordre que l'on attend. Ç'aurait permis de simplifier un chouïa quelques lignes.

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 22/03/2009, 17h00
  2. Problème de path suite à un changement de serveur
    Par Nyutom dans le forum Langage
    Réponses: 9
    Dernier message: 29/10/2007, 15h50
  3. Problème d'accent suite changement de serveur
    Par f1vincent dans le forum Balisage (X)HTML et validation W3C
    Réponses: 1
    Dernier message: 06/04/2007, 16h41
  4. Problème de changement de données personnelles
    Par BnA dans le forum Langage
    Réponses: 9
    Dernier message: 15/05/2006, 14h02
  5. problème d'état suite à changement de version
    Par moicats dans le forum Access
    Réponses: 4
    Dernier message: 11/04/2006, 16h16

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