steph_bow has asked for the wisdom of the Perl Monks concerning the following question:

Hello, Dear Monks,

I wish to construct an output file which merges the data from three input files. I did it with two input fils by using a hash table but I don't know how to do it with three files.

My two input files are excel csv files which have the following form

cake_number;first_price cake_1;3; cake_2;4; cake_3;9; cake_4;7; cake_9;8;
and
cake_number;second_price cake_1;5; cake_2;5; cake_3;5; cake_6;9; cake_10;1;

Here is the output file (I have not tested yet)

cake_number;frist_price;second_price; cake_1;3;5; cake_2;4;5; cake_3;9;5;

Here is my program with two input files

my %hash_table_1; open(INFILE_1, "<$infile_1"); while (my $line_1 = <INFILE_1>){ my @Elements_1 = split ';', $line_1; chomp($Elements_1[1]); $hash_table_1{$Elements_1[0]} = $Elements_1[1]; } my %hash_table_2; open(INFILE_2, "<$infile_2"); while (my $line_2 = <INFILE_2>){ my @Elements_2 = split ';', $line_2; chomp($Elements_2[1]); $hash_table_2{$Elements_2[0]} = $Elements_2[1]; } my @KEYS_1 = keys(%hash_table_1); my @KEYS_2 = keys(%hash_table_2); my $key_1; foreach $key_1(@KEYS_1){ if ( defined $hash_table_2{$key_1}){ print OUTFILE "$key_1;$hash_table_1{$key_1};$hash_table_2{$key_1}\ +n"; } } close OUTFILE; close INFILE_1; close INFILE_2;

I do not know how to do it if I add a third column "third price". Could you give me some advice ? Thanks a lot

Replies are listed 'Best First'.
Re: hash table with three input files
by moritz (Cardinal) on Feb 11, 2008 at 16:17 UTC
    You can store each price in a list, and all the lists in a hash:
    my %prices; # read all files: for $fn (@files){ open (my $file, '<', $fn) or die "Can't open '$fn' for reading: $!" +; while (<$file>){ chomp; my @items = split m/;/, $_; push @{$prices{$items[0]}, $items[1]; } } # print output: for my $k (sort keys %prices){ print "$k;", join(';', @{$prices{$k}}), $/; }

    This works for an arbitrary number of files, but if some prices are only present in some files, the result doesn't show which prices comes form which file.

      Thanks a lot for your help ! moritz

      Concerning your remark to overcome the problem, could this work ? Thanks

      while (<$file>){ chomp; my @items = split m/;/, $_; if (defined($items[1])){ push @{$prices{$items[0]}, $items[1]; } else{ # add a ";" when there is a value void $prices{$items[0]} = "$prices{$items[0]}".";"; } }
Re: hash table with three input files
by svenXY (Deacon) on Feb 11, 2008 at 16:16 UTC
    Hi,
    this looks a lot like homework to me, but to give you a hint:
    Use a Hash of arrays (HoA) with the cake name as the hash key and push all three prices into an anonymous array referenced by the hash key.

    The data structure should then look like:
    { cake_1 => [ 3, 5, x ], cake_2 => [ ... }

    Regards,
    svenXY
Re: hash table with three input files
by j1n3l0 (Friar) on Feb 11, 2008 at 17:08 UTC
    If you want to keep track of which price comes from which file this may help:

    #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; my %info_for; for my $file (@ARGV) { open my $FH, '<', $file or die $!; while ( my $line = <$FH> ) { my ( $cake, $price ) = split /;/, $line, 3; push @{ $info_for{$cake}{files} }, $file; push @{ $info_for{$cake}{prices} }, $price; } close $FH; } print Dumper \%info_for; exit 0; __END__ $VAR1 = { 'cake_2' => { 'files' => [ 'cakes1.txt', 'cakes2.txt', 'cakes3.txt' ], 'prices' => [ '4', '5', '4' ] }, 'cake_10' => { 'files' => [ 'cakes2.txt' ], 'prices' => [ '1' ] }, 'cake_9' => { 'files' => [ 'cakes1.txt' ], 'prices' => [ '8' ] }, 'cake_4' => { 'files' => [ 'cakes1.txt' ], 'prices' => [ '7' ] }, 'cake_6' => { 'files' => [ 'cakes2.txt' ], 'prices' => [ '9' ] }, 'cake_1' => { 'files' => [ 'cakes1.txt', 'cakes2.txt', 'cakes3.txt' ], 'prices' => [ '3', '5', '3' ] }, 'cake_3' => { 'files' => [ 'cakes1.txt', 'cakes2.txt', 'cakes3.txt' ], 'prices' => [ '9', '5', '9' ] } };

    Hope that helps =)


    Smoothie, smoothie, hundre prosent naturlig!