Andrej Kastrin am Montag, 30. Januar 2006 16.50:
> John Doe wrote:
> >Andrej Kastrin am Montag, 30. Januar 2006 10.14:
> >>Dear all,
> >>
> >>I have bar separated file:
> >>name1|345
> >>name2|201
> >>...
> >>
> >>I store it into a hash;
> >>while (<FILE_A>) {
> >>   chomp;
> >>   ($name,$score) = split (/\|/,$_);
> >>   $hash{$name} = $score;
> >>}
> >
> >Let's assume the resulting hash is %scores.
> >
> >>Then I have second file:
> >>ID - 001
> >>NA - name1
> >>NA - name2
> >>
> >>ID - 002
> >>NA - name2
> >>NA - name4
> >>...
> >>
> >>I match all ID's and NA's:
> >>
> >>while (<FILE_B>) {
> >>   chomp;
> >>   if (/^ID/ {
> >>       $ID = substr($_,5);
> >>   }
> >>    elseif (/^NA/) {
> >>        $NA = substr($_,5)
> >>}
> >>
> >>Now I have to do somethig like;
> >>001 | 345+201
> >>So, I want to read ID and NA fields from second file and then with each
> >>ID print the sum of scores from first file.
> >>Any suggestion. Which structure should I use to do that. Thank's in
> >>advance.
> >
> >Now you could parse FILE_B and use another twodimensional hash to
> > accumulate the scores by ID for each name. The loop could look like
> > (untested):
> >
> >my %sums;
> >my $id;
> >while (<FILE_B>) {
> >   chomp;
> >   next if (($id)=$_=~/^ID - (\d+)/);
> >   next unless my ($na)=$_=~/^ID - (\w+)/;
> >   $sums{$id}->{$na}+=$scores{$na};
> >}
> >
> >foreach my $id (sort keys %sums) {
> >   print "ID $id\n";
> >   foreach my $name (sort keys %{$sums{$id}}) {
> >      print "name: $name - scores: ",
> >             $sums{$id}->{$name}, "\n";
> >   }
> >}
> >
> >(All handling of possible errors is missing here)
> >
> >
> >hth,
> >joe
>
> I'm totally confused now and I have no more ideas... Thank's for your
> reply Joe, but I didn't manage. Here is the more real example:

My answer above is obviously not appropriate to the following quite different 
example...

[1]
> First file: (I modify it)
> 270|Germany|Hospitals|Poland
> 272|Germany|History
> 273|Physiology|Poland|Portraits

Quite different from:

   name1|345

[2]
> Second file:
> Germany|100
> History|200
> Hospitals|50
> Poland|50
> Physiology|10
> Portrait|10
(I assume you mean 'portraits' here)

Quite different from:

   ID - 001
   NA - name1
   NA - name2

   ID - 002

[3]
> Output file:
> 270|100|50|50|200 #270 is the key in table 1; 
>                              100, 50, 50 are values for 
>                               nouns from second file, 200 is the sum of them
> 272|100|200|300
> 273|10|50|10|70

Ok, you want [3] from [1] and [2]?
If yes, here is the script, I tested it, and it produces the output you like:

#!/usr/bin/perl

use strict;
use warnings;

# Make a lookup hash of file 2.
# haskeys are keys, hashvalues names of the file.
# It is assumed that a name only occurs once in the file.
#
my %lookup;
open (my $fh2, '<', 'file2') or die;
while (<$fh2>) {
  chomp;
  my ($name, $score)=split /\|/;
  $lookup{$name}=$score;
}
close $fh2 or die;


# Now in every line of file1 all names are replaced
# by their score (?) value found in the lookup hash
# and a sum is added at the end. The line is
# directly printed out.
#
open (my $fh1, '<', 'file1') or die;
open (my $fh3, '>', 'file3') or die;
while (<$fh1>) {
  chomp;
  my ($num, @entries)=split /\|/;

  # replace names by scores. If no score found,
  # take score=0
  #
  @entries=map {$lookup{$_}||0} @entries;

  my $sum=0;
  $sum+=$_ for @entries;

  print $fh3 join '|', $num, @entries, $sum;
  print $fh3 "\n";
}
close $fh1 or die;
close $fh3 or die;




-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to