2015-07-22 2 views
1

Je crée un script de pré-traitement qui va lire dans un fichier csv, regardez deux champs (P_ID et don_date), concaténer les deux ensemble pour créer une clé pour mon hachage, puis conservez la ligne (scindée en tableau) comme valeur pour la clé. Si une autre ligne du fichier a le même p_id et don_date (qui correspondent à ma clé de hachage), je veux prendre les autres valeurs que vous voyez dans le code et les ajouter aux valeurs de l'entrée de hachage existante. Je fais quelques tests, mais je suis un peu confus quant à la façon dont le référencement/décréférencement et tout ce qui fonctionne dans Perl (je suis un gars Python), de sorte que chaque ligne aura une valeur unique P_ID/Don_Date, ou bien il sera enroulé dans un existant.J'ai du mal à obtenir des valeurs dans un hachage

my @lineFields =(); 
my %rollUpHash =(); 

# Open file and loop through lines 
#foreach my $line (<INFH>) 
while(my $line = <INFH>) 
    { 
     # chomp($line); 
     # print STDERR "New line in file\n"; 
     # <STDIN>; 
     @lineFields = split(/,/, $line); 

     # Pull out pertinent values for possible roll-up into a total 
     my $p_id = $lineFields[18]; 
     my $don_date = $lineFields[19]; 
     my $nd_amt = $lineFields[14]; 
     my $deduct_amt = $lineFields[15]; 
     my $nondeduct_ytd = $lineFields[16]; 
     my $deduct_ytd = $lineFields[17]; 
     my $amount = $lineFields[24]; 
     my $anonymous = $lineFields[26]; 
     my $int_code_ex0003 = $lineFields[39]; 
     my $int_code_ex0006 = $lineFields[40]; 
     my $int_code_ex0028 = $lineFields[41]; 
     my $sumDeduct_NonDeduct_ytd = $deduct_ytd + $nondeduct_ytd; 
     my $hashKey = $p_id . $don_date; 
     # say "P_ID is $p_id\nDon_Date is $don_date\nND_Amt is $nd_amt\nDeduct_Amt is $deduct_amt\nNonDeduct_YTD is $nondeduct_ytd\nDeduct_YTD is $deduct_ytd\nAmount is $amount\nAnonymous is $anonymous\n0003 is $int_code_ex0003\n0006 is $int_code_ex0006\n0028 is $int_code_ex0028"; 
     # say "hashKey is $hashKey"; 
     # say "$sumDeduct_NonDeduct_ytd"; 

     if (exists($rollUpHash{$hashKey})) 
     { 
      say("Same key found, summing up!") 
      $rollUpHash{$hashKey}[14] += $lineFields[14]; 
      $rollUpHash{$hashKey}[15] += $lineFields[15]; 
      $rollUpHash{$hashKey}[16] += $lineFields[16]; 
      $rollUpHash{$hashKey}[17] += $lineFields[17]; 
      $rollUpHash{$hashKey}[24] += $lineFields[24]; 
      push @{$rollUpHash{$hashKey}}, $sumDeduct_NonDeduct_ytd; 
      # print %rollUpHash; 
     } 
     else 
     { 
      $rollUpHash{$hashKey} = \@lineFields; 
     } 
     foreach my $key (keys %rollUpHash) 
     { 
      print OUTFH "$key is @{$rollUpHash{$key}}"; 
     } 

Voici trois lignes de données d'entrée: frotté

152099-00001,,100,100,400,100,175,100,700,200,200,500,0,0,0,300,0,2575,105666,10/28/14,197800,23764962,"Jefferson,Mark",300,1004,N,N,N,D,Mike and Bonnie,Mike and Bonnie Gregorovitch,715 81st St NE,,,Central,IL,52402-7256,UNITED STATES,,,,,Y,[email protected],,(888) 888-8888,"Jefferson,Mark",2222B,BASIC,, 
342029-00015,,200,0,400,200,200,200,200,200,200,200,0,0,0,200,0,2000,3184444,09/27/14,197800,40949,"Macrow,Gregory",100,1004,N,N,N,D,John and Amber, John and Amber Meadows,PO Box 706,,,Logan,MD,01111-0704,UNITED STATES,,,,,Y,[email protected],,(999) 999-9999,"Macrow,Gregory",2222B,BASIC,, 
342029-00014,,200,0,400,200,200,200,200,200,200,200,0,0,0,200,0,2000,3184444,09/27/14,197800,22145,"Bartholomew,Vincent",100,1004,N,N,N,D,John and Amber, John and Amber Meadows,PO Box 706,,,Logan,MD,01111-0704,UNITED STATES,,,,,Y,[email protected],,(999) 999-9999,"Bartholomew,Vincent",2222B,BASIC,, 

Toute aide de tri ce problème en serait très apprécié!

+0

Quel est le problème/question? Pouvez-vous montrer 3 lignes d'entrée? – choroba

+0

La seule chose étrange que je vois est 'push @ {$ rollUpHash {$ hashKey}}, $ sumDeduct_NonDeduct_ytd;' – ikegami

+0

@choroba il a été ajouté à l'OP. – flybonzai

Répondre

2

On ne sait pas ce que vous voulez faire avec le $sumDeduct_NonDeduct_ytd: voulez-vous vraiment ajouter de nouvelles sommes à la ligne , ou simplement remplacer la dernière colonne avec?

En outre, l'utilisation de split /,/ sur un fichier CSV contenant des guillemets est incorrecte. Utiliser Text::CSV:

#! /usr/bin/perl 
use warnings; 
use strict; 
use feature qw{ say }; 

use Text::CSV; 

use constant { 
    ND_AMT  => 14, 
    DEDUCT_AMT => 15, 
    NONDEDUCT_YTD => 16, 
    DEDUCT_YTD => 17, 
    PID   => 18, 
    DON_DATE  => 19, 
    AMOUNT  => 24, 
}; 


my $csv = 'Text::CSV'->new({ binary => 1 }); 

my %hash; 
open my $IN, '<:encoding(utf-8)', shift or die $!; 
while (my $row = $csv->getline($IN)) { 
    my $key = join ':', @{$row}[PID, DON_DATE]; 
    if (exists $hash{$key}) { 
     $hash{$key}[$_] += $row->[$_] for ND_AMT, DEDUCT_AMT, NONDEDUCT_YTD, 
              DEDUCT_YTD, AMOUNT; 
     my $sum = $row->[DEDUCT_YTD] + $row->[NONDEDUCT_YTD]; 
     $hash{$key}[-1] = $sum;  # Or do you mean something else? 
    } else { 
     $hash{$key} = $row;   # You can store the reference directly, 
    }        # as you get a fresh new one for each iteration. 
} 

for my $key (keys %hash) { 
    say "$key : @{ $hash{$key} }"; # You should rather use $csv->print. 
} 
+0

Merci pour les conseils !! Je vais les parcourir pour essayer de les comprendre un peu mieux. – flybonzai

+0

Merci monsieur, cela a fait exactement ce que je voulais. Maintenant, j'ai juste besoin de parcourir le module TEXT :: CSV pour comprendre toute la syntaxe! :) – flybonzai

0

Il y a différents problèmes avec ceci:

problèmes d'adresse en premier lorsque les touches ne se répète pas

  1. Votre déclaration d'impression foreach est en boucle.

J'ai imprimé la sortie et c'est bizarre. 3 lignes d'entrée donne 4 lignes de sortie (ajouter plus de nouvelles lignes pour voir que)

J'aiderai fixer d'autres questions telles que les mises à jour

1

Vous stockez un pointeur vers la variable @lineFields dans le hachage rollUpHash, mais c'est la même variable. Donc, vous finissez par hachage dont toutes les valeurs sont le pointeur vers le même tableau que le contenu que vous détruisez et remplissez à plusieurs reprises avec un autre contenu. Cela n'a pas de sens. Vous devez déplacer my @lineFields l'intérieur du cycle ou changement ligne

$rollUpHash{$hashKey} = \@lineFields; 

dans while

$rollUpHash{$hashKey} = [@lineFields]; 
+0

Fantastique, merci. Est-ce que le [] autour de mon tableau en fait une copie? – flybonzai

+0

Oui, exactement. Vous pouvez y penser comme '[@a]' est l'équivalent de 'do {my @b = @a; \ @b} 'où' = 'copie le contenu du tableau. Mais personnellement, je préférerais déplacer la déclaration de variables à l'intérieur de la boucle. –