Re: How can I group lines in a file?
by zwon (Abbot) on May 16, 2009 at 17:54 UTC
|
use strict;
use warnings;
my %res;
while (<DATA>) {
my ( $name, $weight ) = split /\s+/;
push @{ $res{$name} }, $weight;
}
for ( sort keys %res ) {
print "$_ ", join( ",", @{ $res{$_} } ), "\n";
}
__DATA__
jim 14
john 23
ernest 38
matilda 43
jim 34
ernest 27
john 44
matilda 22
| [reply] [d/l] |
Re: How can I group lines in a file?
by BrowserUk (Patriarch) on May 17, 2009 at 00:30 UTC
|
There's nothing wrong with the other solutions offered, but it can be done more concisely with no loss of clarity:
my %HoA; ## Typo corrected
open my $fh, '<', 'junk.dat' or die $!;
/(\S+)\s+(\S+)/ and push @{ $HoA{ $1 } }, $2 while <$fh>;
close $fh;
pp \%HoA;
{
ernest => [38, 27],
jim => [14, 34],
john => [23, 44],
matilda => [43, 22]
}
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
|
|
Hi BrowserUk,
I like your solution but I'm not sure I understand it properly. Why does this line work?
/(\S+)\s+(\S+)/ and push @{ $HoA{ $1 } }, $2 while <$fh>;
I broke the line into 3 parts (split, push and the reading the file) and I understand what each part does but what I don't understand is why it worked.
For example, should I read the line from right to left? So, read the file then split "and" push??? Why does split and push combo work together. This is what I don't understand.
If you can explain it or point me to the proper documentation, I would really appreciate it. Thanks
| [reply] [d/l] |
|
|
split is a function, so there is no split.
That code is equivalent to
while( <$fh> ){
if(/(\S+)\s+(\S+)/){
push @{ $HoA{ $1 } }, $2;
}
}
to test, add before the if
warn 'scalar ', /(\S+)\s+(\S+)/;
warn 'list ', join '|', /(\S+)\s+(\S+)/;
| [reply] [d/l] [select] |
|
|
|
|
|
|
|
|
| [reply] |
|
|
| [reply] [d/l] [select] |
|
|
|
|
Re: How can I group lines in a file?
by toolic (Bishop) on May 16, 2009 at 19:01 UTC
|
| [reply] |
Re: How can I group lines in a file?
by johngg (Canon) on May 16, 2009 at 23:10 UTC
|
zwon has pointed you in the right direction but I note that your output is not sorted by name but retains the order in which names first occured in the data. To keep that order you will need to preserve it in the hash and sort on it when printing.
use strict;
use warnings;
my $order = 0;
my %names = ();
while( <DATA> )
{
my( $name, $value ) = split;
$names{ $name }->{ order } = ++ $order
unless exists $names{ $name };
push @{ $names{ $name }->{ values } }, $value;
}
print do
{
local $" = q{,};
qq{$_ @{ $names{ $_ }->{ values } }\n};
}
for sort
{
$names{ $a }->{ order } <=> $names{ $b }->{ order }
}
keys %names;
__END__
jim 14
john 23
ernest 38
matilda 43
jim 34
ernest 27
john 44
matilda 22
The output.
jim 14,34
john 23,44
ernest 38,27
matilda 43,22
I hope this is of interest.
| [reply] [d/l] [select] |
|
|
use strict;
use warnings;
my %res;
while (<DATA>) {
my ( $name, $weight ) = split /\s+/;
push @{ $res{$name} }, $weight;
}
for ( sort { length($a) cmp length($b) } keys %res ) {
print "$_ ", join( ",", @{ $res{$_} } ), "\n";
}
for ( sort { $res{$a}->[0] <=> $res{$b}->[0] } keys %res ) {
print "$_ ", join( ",", @{ $res{$_} } ), "\n";
}
__DATA__
jim 14
john 23
ernest 38
matilda 43
jim 34
ernest 27
john 44
matilda 22
| [reply] [d/l] |
Re: How can I group lines in a file?
by bichonfrise74 (Vicar) on May 17, 2009 at 06:09 UTC
|
oops, my bad. When I was writing my own version, I used "split" to get the values which is basically the regex thing that BrowserUk did. Also, my version is similar to what you just wrote... Read the file, get the values, push it in a hash of array.
But BrowserUk's version was done in a single line which I'm still perplexed. Why does it work? (regex thing "and" pushing it in a hash of array).
How does "and" work? How can it get the regex values and push it to HoA? Thanks. | [reply] |