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

I have some data that has the column titles (ItemName1...) for each of the objects (Apple, Orange, ....), and then multiple lines of objects that correspond to the column titles. What I am trying to do, but don't know where to go next, is to put all the data in a sort of hash array. The column titles would be the keys of the hash, but there would be a separate line for each line of data/objects. This is the code where I am at so far:
#!/usr/bin/perl -w use strict; use Data::Dumper; my $rawdata = qq| <COLUMNS>~ItemName1~ItemName2~ItemName3~ItemName4~ItemName5~</COLUMNS> <DATA>~Apple~Orange~Banana~Pear~Watermelon~</DATA> <DATA>~Blue~Red~Yellow~Brown~Purple~</DATA> <DATA>~Uno~Dos~Tres~Cuatro~Cinco~</DATA> |; my @datalines = split("\n",$rawdata); my @listings; my $header; foreach my $line (@datalines) { if ($line =~ /^<COLUMNS>(.+)<\/COLUMNS>/xg) { $header = $1; } elsif ($line =~ /^<DATA>(.+)<\/DATA>/xg) { push(@listings, $1); } } print Dumper(\$header); print Dumper(\@listings);


Michael
Thanks for your help!

Replies are listed 'Best First'.
Re: Complicated Hash with array
by GrandFather (Saint) on Aug 08, 2006 at 05:05 UTC

    Without any error checking this works for you sample:

    use warnings; use strict; my $rawdata = qq| <COLUMNS>~ItemName1~ItemName2~ItemName3~ItemName4~ItemName5~</COLUMNS> <DATA>~Apple~Orange~Banana~Pear~Watermelon~</DATA> <DATA>~Blue~Red~Yellow~Brown~Purple~</DATA> <DATA>~Uno~Dos~Tres~Cuatro~Cinco~</DATA> |; my @datalines = grep {length} split "\n",$rawdata; my @listings; my $header; foreach my $line (@datalines) { if ($line =~ /^<COLUMNS>(.+)<\/COLUMNS>/) { $header = $1; } elsif ($line =~ /^<DATA>(.+)<\/DATA>/) { push(@listings, $1); } } my %hoa; my @keys = grep {length} split '~', $header; for my $listing (@listings) { my @list = grep {length} split '~', $listing; push @{$hoa{$keys[$_]}}, $list[$_] for 0..$#keys; } print "$_ => @{$hoa{$_}}\n" for sort keys %hoa;

    Prints:

    ItemName1 => Apple Blue Uno ItemName2 => Orange Red Dos ItemName3 => Banana Yellow Tres ItemName4 => Pear Brown Cuatro ItemName5 => Watermelon Purple Cinco

    DWIM is Perl's answer to Gödel
      That works great. I will need to stare at that for a while to process it all though.

      Any suggestions on a way to parse through the data line by line (of the DATA rows) by calling it by the item name? Something like below, although this obviously doesn't work with the current hash, this is what I envisioned but am unsure of how to accomplish it:
      foreach my $data (@datalineshasharraything) { print "Item1 is ", $data{'ItemName1'}; print "Item2 is ", $data{'ItemName2'}; }
      Not sure if that is doable, as it is beyond my scope of Perl understanding. Any suggestions? Thanks


      Michael Jensen
        You can accomplish that inside the for (@listings) loop of GrandFather's solution by using a hash slice.
        for my $listing (@listings) { my @list = grep {length} split '~', $listing; my %data; @data{@keys} = @list; print "Item1 is ", $data{'ItemName1'}, $/; print "Item2 is ", $data{'ItemName2'}, $/; push @{$hoa{$keys[$_]}}, $list[$_] for 0..$#keys; }

        -- Hofmator