2010-11-22 15 views
1

J'ai un fichier csv (très énorme) avec le format suivant.perl calculer la différence de colonnes dans le fichier csv

key1,val1,val2,val3... ,valn 
key2,val2,val5,val1....,valn 
... 
... 
keyn,val7,val9,val11....,valn 
key1,val2,val4,val8.....,valn 
key2,val10,val12,val14..., valn 
... 
... 
keyn,val2,val4,val8.....,valn 
key1,val3,val5,val7... ,valn 
key2,val0,val9,val3....,valn 

key1 à keyn (et leurs valeurs) se répète plusieurs fois dans le fichier csv.

Les valeurs (val1, valn) sont doubles (flottant).

ce que je veux imprimer:

1) Dès le début du fichier, pour chaque clé que je veux calculer la différence entre les valeurs de colonne (val2, Val4, VAL6 par exemple) à l'apparition prochaine de la clé .

donc par exemple

key1,2,4,6 
key2,3,5,7 
... 
... 
key1,4,6,8 
key2,4,6,8 

Je veux imprimer

key1: Diff de précédent record est key1,2,2,2 key2: Diff de précédent record est key2,1,1, 1 ..

keyn: Diff de disque précédent est ...........

2) est-ce que ce à plusieurs reprises pour les occurrences consécutives chacune o f chaque touche.

Voici ce que je suis venu à (stocker des valeurs en hachage)

#!/usr/bin/perl 

my %hash; 
open my $fh, '<', 'file1.csv' or die "Cannot open: $!"; 
while (my $line = <$fh>) { 
    $line =~ s/\s*\z//; 
    my @array = split /,/, $line; 
    my $key = shift @array; 
    $hash{$key} = \@array; 
} 
close $fh; 
+0

désolé ... pour le mauvais id - :) c'était rapide post ... j'ai une adresse e-mail valide –

+0

@mystery_man Je suppose que vous êtes en bonne compagnie http://en.wikipedia.org/wiki/Austin_Powers:_International_Man_of_Mystery Plus important encore, vous n'avez pas bien expliqué votre problème. –

+0

Cela me semble familier. Devoirs? –

Répondre

0

Mon essai:

use strict; 
use warnings; 

use Text::CSV_XS; 

use Math::Matrix; 



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

my %hash; 

my @results; 

open my $fh, '<', 'file1.csv' or die "Cannot open: $!"; 

while (my $line = <$fh>) { 

    if ($csv->parse($line)) { 

    my @array = $csv->fields; 
    my $key = shift @array; 

    if (! exists $hash{$key}) { 
     $hash{$key} = \@array; 
     next; 
    } 



    my $previous_record = Math::Matrix->new($hash{$key}); 
    my $current_record = Math::Matrix->new(\@array); 

    my $new_record = $previous_record->add($current_record->negative); 

    push @results, @$new_record; 

    $hash{$key} = \@array; 



    } 
    else { 
    my $err = $csv->error_input; 
    print "error parsing: $err\n"; 
    } 

} 
+0

Cela a également fonctionné. Mais, il a calculé la différence entre l'enregistrement précédent et l'enregistrement en cours. Je suppose que je n'ai pas expliqué le problème plus précisément. Merci beaucoup pour l'effort. –

2

Vous pouvez essayer de faire:

# get the key. 
    my $key = shift @array; 

    # see if the key is already seen. 
    if(exists $hash{$key}) { 
      # get ref to previous record of this key. 
      my $ref = $hash{$key}; 

      # print key. 
      print "$key,"; 

      # a new array. 
      my @new_array; 

      # populate the new array. 
      for(my $i=0;$i<=$#array;$i++) { 
        $new_array[$i] = $array[$i] - $$ref[$i]; 
      } 

      # join the array elements with comma. 
      print join",",@new_array; 
      print "\n"; 
    } 

    # add/replace the current array as value for the current key. 
    $hash{$key} = \@array; 

You can see the working code here

+0

Merci beaucoup, codaddict. Cela a fonctionné parfaitement sauf pour la première clé. –