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

Replies are listed 'Best First'.
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.

    After Compline,
    Zaxo

Re: rearranging text
by Roger (Parson) on Dec 02, 2003 at 03:19 UTC
    How about this? ;-)
    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
      Hey Roger,

      Can you enlighten on the purpose of '\s+' in the split expression?

        \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.

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;

      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"; }

      use perl;

Re: rearranging text
by Zed_Lopez (Chaplain) on Dec 02, 2003 at 08:00 UTC

    or, getting sillier...

    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
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*$//; }
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;
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!