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

Hi all, I have 2 files:
FILE 1 complex.1 1.356 complex.2 1.879 etc file 2 12.02 /home/complex.2out 10.25 /home/complex.1out etc
i need to merge the data in file 2 to the relevant rows in file 1 based on the complex number. However, the order in file 2 is not the same as file 1. Thought hash would be useful to lookup the complex numbers. I can merge the data but how can i incorporate the values in file 1 also?
$string = 'complex'; open(REF, "<file1"); chomp; my %pd_file = map { /^(\S+)\s+(\S+).*/; } <REF>; close(REF); open (ET, "<file2"); while (<ET>) { chomp; /^(\S+\s+\S+)\s+.*($string\.\d+).*$/; print OUT ($1, $pd_file{$2}) if (exists($pd_file{$2}));
myoutput is
complex.1 10.25 complex.2 12.02

Janitored by Arunbear - retitled from 'hash' and balanced code tag around output

Replies are listed 'Best First'.
Re: How can I merge data using a hash?
by Zed_Lopez (Chaplain) on Oct 10, 2004 at 22:01 UTC

    I don't know what to recommend, because I don't know what you mean by merge. If you want to have access to both values, you could use arrayrefs as the values of your hash, and push each value on. Or you could use two different hashes, which might be more sensible depending on what you actually wanted to do with them.

    What would be the output you'd desire from processing the two files in your example?

      the output would look like
      complex.1 1.356 10.25 complex.2 1.879 12.02
Re: How can I merge data using a hash? (golf it)
by ccn (Vicar) on Oct 10, 2004 at 22:40 UTC

    perl -ane '$|?($F[1]=~/complex.\d/and$a{$&}=$F[0]):($b{$F[0]}=$F[1]);$ +|||=eof}{print"$_ $b{$_} $a{$_}\n"for keys%b' file1 file2
Re: How can I merge data using a hash?
by pg (Canon) on Oct 10, 2004 at 21:57 UTC

    As for data structure, how about hash of array ref. The hash key is your complex number. Each array ref contains two numbers, one from file1, and one from file2.

      never used references to an array, any advice?

        Some code: (you may have to refine a bit, do things like output formating, sorting etc.)

        use Data::Dumper; use strict; use warnings; my $hash; open(FILE, "<", "file1.txt"); while (<FILE>) { my ($k, $v) = split " "; $hash->{$k}->[0] = $v; } close FILE; open(FILE, "<", "file2.txt"); while (<FILE>) { my ($v, $k) = split " "; $k = /(complex\.\d+)/; $hash->{$1}->[1] = $v; } close FILE; print Dumper($hash); open (OUT, ">", "out.txt"); for my $key (keys(%$hash)) { print OUT $key . " " . $hash->{$key}->[0] . " " . $hash->{$key}->[ +1] . "\n"; } close OUT;
        perldoc perlreftut

        Caution: Contents may have been coded under pressure.
Re: How can I merge data using a hash?
by TedPride (Priest) on Oct 10, 2004 at 22:38 UTC
    I'm assuming every line contains data and that the files are in tab delimited format.
    use strict; my @file1 = ( "complex.1\t1.356\n", "complex.2\t1.879\n", ); my @file2 = ( "12.02\t/home/complex.2out\n", "10.25\t/home/complex.1out\n", ); my (%hash, $ref, $values); chomp(@file1); chomp(@file2); foreach (@file1) { $_ =~ /^complex\.(\d+)\t([\d\.]+)$/; $hash{$1}->[0] = $2; } foreach (@file2) { $_ =~ /^([\d\.]+)\t\/home\/complex.(\d+)out$/; $hash{$2}->[1] = $1; } foreach (sort {$a <=> $b} keys %hash) { $ref = $hash{$_}; $values = join("\t", @$ref); print "complex.$_\t$values\n"; }
      could you explain this:
      $hash{$1}->[0] = $2
      is it a reference to an array? so the key is $1...
        Yes, it's a reference to an array. For instance:
        $hash{$1}->[0] = $2; $ref = $hash{$1}; print @$ref[0];
        $ref points to the array. @$ref is the array that $ref points to.