texuser74 has asked for the wisdom of the Perl Monks concerning the following question:
Dear Friends,
I have a ascii text file with the following kind of text
a, 1
aa, 3
aa, 5
aa, 8
b, 2
b, 3
bb, 5
this i want to arrange as
a, 1
aa, 3, 5, 8
b, 2, 3
bb, 5
my input file is already in sorted form, but how to arrange the numbers like this
please help
Re: rearranging text
by Zaxo (Archbishop) on Dec 02, 2003 at 03:18 UTC
|
Collect your data in a hash of arrays, pushing on the data as it is seen,
my %hash;
while (<IN>) {
chomp;
my @foo = split /, /;
push @{$hash{$foo[0]}}, 0+$foo[1];
}
for (sort keys %hash) {
print OUT join ', ', $_, @{$hash{$_}};
print OUT $/;
}
The 0+$foo[1] is there to make the value numeric and so strip trailing whitespace.
| [reply] [d/l] [select] |
Re: rearranging text
by Roger (Parson) on Dec 02, 2003 at 03:19 UTC
|
use strict;
my $prev;
while (<DATA>) {
next if /^\s*$/;
chomp (my ($curr, $val) = split /,\s+/);
print $prev ? "\n" : "", $prev = $curr if $curr ne $prev;
print ", $val";
}
print "\n";
__DATA__
a, 1
aa, 3
aa, 5
aa, 8
b, 2
b, 3
bb, 5
| [reply] [d/l] |
|
| [reply] |
|
\s means match a single space, \s+ means match one or more spaces.
In the example below:
use strict;
use Data::Dumper;
my $string = 'a, 1, 2, 3';
my @split_comma = split /,/, $string;
print "\@split_comma =>", Dumper(\@split_comma);
my @split_comma_space = split /,\s+/, $string;
print "\@split_comma_space =>", Dumper(\@split_comma_space);
Notice in the output -
@split_comma =>$VAR1 = [
'a',
' 1',
' 2',
' 3'
];
@split_comma_space =>$VAR1 = [
'a',
'1',
'2',
'3'
];
Splitting with comma only leaves spaces in array elements, while splitting with comma+space leaves no spaces in array elements.
What split /,\s+/ does is to set the separator as comma followed by 1 or more spaces, thus eliminating the spaces from the result.
| [reply] [d/l] [select] |
Re: rearranging text
by BUU (Prior) on Dec 02, 2003 at 03:14 UTC
|
my %all;
while(<>)
{
my ($k,$v)=split/,/;
$all{$k}.=",$v";
}
print map { "$_, $all{$_} "} keys %all;
| [reply] [d/l] |
|
This leads to possibly ugly output as there will be an extra comma in the output
Also will a value appear more than once, and should the values be sorted as well? Im thinking a HoH might be overkill, but another (better?) way to do it.
my %all;
while (<>) {
s/\s+//g;
my($k, $v) = split /,/;
next unless defined $k and defined $v;
$all{$k}{$v}++;
}
for ( sort keys %all ) {
print "$_, ", join(', ', sort keys %{ $all{$_} }), "\n";
}
| [reply] [d/l] |
Re: rearranging text
by Zed_Lopez (Chaplain) on Dec 02, 2003 at 08:00 UTC
|
while (<DATA>) {
print /(\d+)/ ? ", $1" : $s{$_}++ ? '' : $a++ ? "\n$_" : $_ for spli
+t /\s*,\s*/;
}
print "\n";
__DATA__
a, 1
aa, 3
aa, 5
aa, 8
b, 2
b, 3
bb, 5
| [reply] [d/l] |
Re: rearranging text
by sphere0001 (Initiate) on Dec 02, 2003 at 18:30 UTC
|
I'm pretty new to perl as you can probably tell from my solution, but here you go anyway.
#!/usr/bin/perl -w
use strict;
my $someDatFile = 'datfile.dat'; #the file you need read in
open( DATFILE, $someDatFile ) or die "Cannot open $someDatFile";
my $currentPrefix;
while( <DATFILE> )
{
my( $prefix, $postfix ) = split ( /,/, $_ );
&cleanUp( \$prefix );
&cleanUp( \$postfix );
if( ( !$currentPrefix ) or ( $currentPrefix ne $prefix ) )
{
if( $currentPrefix )
{
print "\n";
}
$currentPrefix = $prefix;
print "$prefix, $postfix";
}
else
{
print ", $postfix";
}
}
print "\n";
close( DATFILE );
sub cleanUp
{
my $ref = shift;
$$ref =~ s/^\s*//;
$$ref =~ s/\s*$//;
}
| [reply] [d/l] |
Re: rearranging text
by kesterkester (Hermit) on Dec 02, 2003 at 15:56 UTC
|
Here's how I'd do it (pretty similar to Zaxo's and Roger's):
my %hash;
while (<DATA>) {
chomp ( my ( $key, $val ) = split /,\s+/ );
push @{$hash{$key}}, $val;
}
print "$_ ", join( ", ", @{$hash{$_}} ), "\n" foreach sort keys %hash;
| [reply] [d/l] |
Re: rearranging text
by Willard B. Trophy (Hermit) on Dec 03, 2003 at 15:38 UTC
|
Doesn't the troff/TeX utility "makeindex" do this for you?
-- bowling trophy thieves, die!
| [reply] |
|
|