Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Converting Column Into Row

by sdslrn123 (Novice)
on Jun 20, 2006 at 12:47 UTC ( [id://556374]=perlquestion: print w/replies, xml ) Need Help??

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

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://556374]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (3)
As of 2024-04-25 17:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found