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

A = 1 A = 2 A = 3 B = 5 B = 1 B = 7 e.t.c C = .....
Is there a way to convert this format to:
A = 1,2,3 B = 5,1,7 C = ... . . . Z = ...
I am thinking while in data file split each line to letters and numbers. if next letter matches previous letter push into an array otherwise create a new array called B? Thanks for any advice. WOW! Thank You very much... EVERYBODY! Just one more thing: What if there is no space between the data? A = 1 A = 2 A = 3 B = 5 B = 1 B = 7 C = 4

Replies are listed 'Best First'.
Re: Converting Column Into Row
by derby (Abbot) on Jun 20, 2006 at 12:52 UTC

    Sure ... just add the data into a hash of arrays where the key is the stuff before the = and the value is an array of the stuff afterwards:

    #!/usr/bin/perl use strict; use warnings; my %hash; while( <DATA> ) { chomp; next unless $_; my( $key, $val ) = split( /\s+=\s+/, $_ ); push( @{$hash{$key}}, $val ); } foreach my $key ( sort keys %hash ) { print $key, " = " . join( ',', @{$hash{$key}} ), "\n"; } __DATA__ A = 1 A = 2 A = 3 B = 5 B = 1 B = 7 C = 4

    -derby
Re: Converting Column Into Row
by holli (Abbot) on Jun 20, 2006 at 12:55 UTC
    Do you need to preserve the order of "A, B, C" or can it be sorted later on?
    A simple hash based solution would be
    while (<DATA>) { my ($key, $val) = split / = /; push @{$data{$key}}, $val; }
    But this looses the order of the keys.


    holli, /regexed monk/

      So track the order too.

      if ( not exists $order{$key} ) { $order{$key} = 0 + scalar keys %order; }

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

        Or use Tie::IxHash on the data hash, before you start filling it.
        use Tie::IxHash; tie %data, 'Tie::IxHash';

        Tie::IxHash actually does pretty much the same thing as your code, under the hood.

Re: Converting Column Into Row
by davorg (Chancellor) on Jun 20, 2006 at 12:56 UTC

    Something like this perhaps:

    use strict; use warnings; my %data; while (<DATA>) { next unless /\S/; chomp; my ($k, $v) = split / = /; push @{$data{$k}}, $v; } foreach (sort keys %data) { print "$_ = ", join(',', @{$data{$_}}), "\n"; } __DATA__ A = 1 A = 2 A = 3 B = 5 B = 1 B = 7
    --
    <http://dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: Converting Column Into Row
by Fletch (Bishop) on Jun 20, 2006 at 13:02 UTC

    Presuming you want to preserve the order and you won't have different interleaved (e.g. A A A B B B C C A B B, where keys seen before reoccur later) you just need to store off the current key's value.

    my( $lastkey, @row ); while( <DATA> ) { chomp; next if /^\s*$/; my( $key, $datum ) = split /\s+=\s+/; if( $key ne $lastkey ) { print "$lastkey = ", join( ",", @row ), "\n" if @row; @row = (); $lastkey = $key; } push @row, $datum; } print "$lastkey = ", join( ",", @row ), "\n" if @row; __END__ A = 1 A = 2 A = 3 B = 5 B = 1 B = 7 C = 8 C = 6 C = 7 C = 5 C = 3 C = 0 C = 9
Re: Converting Column Into Row
by mickeyn (Priest) on Jun 20, 2006 at 13:02 UTC
    Hi,

    A better way is to create a hash containing your arrays as values (I put your input into a file named 'test'):

    use Data::Dumper; my %h; open FH, "test"; while (<FH>) { chomp; next if /^\s*$/; split /=/; push @{$h{$_[0]}}, $_[1]; } close FH; print Dumper \%h;
    output:
    $VAR1 = { 'A ' => [ ' 1', ' 2', ' 3' ], 'B ' => [ ' 5', ' 1', ' 7' ] };

    Enjoy,
    Mickey

Re: Converting Column Into Row
by Jasper (Chaplain) on Jun 20, 2006 at 13:13 UTC
    Or a regular expression..
    $_ = "A = 1 A = 2 A = 3 B = 5 B = 1 B = 7 "; 1 while s/((\w+) = .+) \2 = (.+)/$1, $3/;
Re: Converting Column Into Row
by Moron (Curate) on Jun 20, 2006 at 14:46 UTC
    Seems easier to me to append the ',' + value on the end of the hash values as you first read them in...
    my %hash; while(<>) { chop; my ( $k, $v ) = split /\s*\=\s*/; $hash{ $k } = defined ( $hash{ $k } ) ? $hash{$k } . ",$v" : $v; } while ( my ($k, $v ) = each %hash ) { print "$k = $v\n"; }

    -M

    Free your mind