Perl вычисляет разницу столбцов в CSV-файле - PullRequest
1 голос
/ 22 ноября 2010

У меня есть 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 to keyn (и их значения) повторяется несколько раз в CSV-файле.

значения (val1, valn) являются двойными (с плавающей точкой).

что я хочу напечатать:

1) В начале файла для каждого ключа я хочу вычислить разницу между значениями столбца (val2,val4, val6, например) до следующего вхождения ключа.

, например,

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

Я хочу напечатать

key1: Отличие от предыдущей записи - это key1, 2,2,2 key2: отклонение от предыдущей записи - key2,1,1,1 ..

keyn: отклонение от предыдущей записи ...........

2) Делайте это несколько раз для каждого последующего вхождения каждой клавиши.

Вот что я придумал (сохранение значений в хэше)

#!/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;

Ответы [ 2 ]

2 голосов
/ 22 ноября 2010

Вы можете попробовать:

    # 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;

Рабочий код вы можете увидеть здесь

0 голосов
/ 22 ноября 2010

Моя попытка:

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";
  }

}
...