http://qs1969.pair.com?node_id=475244

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

Greetings

I have a complex data structure as given below
```@data_array_ref = [
mykey1 => {firstkey => 'firstvalue', secondkey => 'secondval' }
mykey2 => {ninza => 'turtle', 'Hurricane' => 'Dennis'}
mykey3 => [ [one,two, three]
mykey4 => [ [4, 5, three] [6, 7, four] [8, 9, five] ]
]
I've tried to get the output as given below from the above data structure but I'm not successful.
Can someone throw some light about the same.
```
mykey1 => firstval, secondval
mykey2 => turtle, Dennis
mykey3 => one, two, three
mykey4 = 4, 5, three, 6, 7, four, 8, 9, five

Replies are listed 'Best First'.
Re: Parsing complex data
by Limbic~Region (Chancellor) on Jul 15, 2005 at 15:13 UTC
chanakya,
Since you have omitted details of your requirements I am going to guess that you know you have an AoHo(H or A) and that you want the keys of the second level H and corresponding values of the (H or A) regardless of which it is.
```for ( @\$data } {
print "\$_ =>";
if ( ref \$_ eq 'ARRAY' ) {
print join ", ", @\$_;
}
else {
print join ", ", sort values %\$_;
}
print "\n";
}
Note: You may have to modify this a bit to get a specific order with your hashes if the simple sort I provided isn't satisfactory. You will also have to modify the depth of ref depending on how many levels deep you need to go. IOW - this isn't fully working code but an idea of how to get started.

Cheers - L~R

Update:Data::Dump::Streamer and/or Data::Dumper may also be of some help. As socketdave points out, your data structure is missing commas and unbalanced and it is hard to say for sure what you want without some more specifics

The structure of your input data also seems pretty hosed to me, but I could be missing something... shouldn't it be something closer to:
```my \$data = [
mykey1 => { 'firstkey' => 'firstvalue', 'secondkey' => 'secondval'
+ },
mykey2 => { 'ninza'    => 'turtle',     'Hurricane' => 'Dennis' },
+
mykey3 => [ [ 'one', 'two', 'three' ] ],
mykey4 => [ [ 4, 5, 'three' ], [ 6, 7, 'four' ], [ 8, 9, 'five' ]
+],
];

L~R's solution has problems:

```output
======
mykey1 =>
HASH(0x1abefc0) =>firstvalue, secondval
mykey2 =>
HASH(0x1abf0a4) =>Dennis, turtle
mykey3 =>
ARRAY(0x1ab5148) =>ARRAY(0x1ab50d0)
mykey4 =>
ARRAY(0x1ab52f8) =>ARRAY(0x1ab5190), ARRAY(0x1ab5208), ARRAY(0x1ab5280
+)

My solution:

```\$data_array_ref = [
mykey1 => {firstkey => 'firstvalue', secondkey => 'secondval' },
mykey2 => {ninza => 'turtle', 'Hurricane' => 'Dennis'},
mykey3 => [ ['one', 'two', 'three'] ],
mykey4 => [ [4, 5, 'three'], [6, 7, 'four'], [8, 9, 'five'] ],
];

my \$i = 0;
while (\$i < @\$data_array_ref) {
my \$key = \$data_array_ref->[\$i++];
my \$val = \$data_array_ref->[\$i++];

print "\$key => ";

if (ref(\$val) eq 'HASH') {
print join ', ',
values %\$val;
}
else
{
print join ', ',
map { @\$_ }
@\$val
}

print "\n";
}

__END__
output
======
mykey1 => firstvalue, secondval
mykey2 => turtle, Dennis
mykey3 => one, two, three
mykey4 => 4, 5, three, 6, 7, four, 8, 9, five

It be somewhat easier if your topmost data structure was a hash, not an array.

map { @\$_ } @\$_ flattens a ref to an array of arrays of scalars, as opposed to @\$_ which only flattens a ref to an array of scalars.

ikegami,
Limbic's solution has problems

It certainly does. This is one of those posts where my brain auto-corrected missing and incorrect information. After the initial post I realized it was lacking and noted it. Thanks for spending more than 2 seconds reading the question before replying - it is afterall Friday.

Cheers - L~R

Re: Parsing complex data
by tcf03 (Deacon) on Jul 15, 2005 at 15:26 UTC
I had a similar question some time back and had some good responses - iterating a hash of (complex?) arrays

Ted
--
"That which we persist in doing becomes easier, not that the task itself has become easier, but that our ability to perform it has improved."
--Ralph Waldo Emerson
Re: Parsing complex data
by themage (Friar) on Jul 15, 2005 at 15:57 UTC
Hi,

I'ld do it like this:
```#!/usr/bin/perl -w

use strict;

sub printstruct {
my \$struct=shift;
my \$main=shift||0;
my \$ret=\$main?"\n":" ";

my \$item;
if (ref \$struct eq "ARRAY") {
for \$item (sort @\$struct) {
printstruct(\$item);
}
} elsif (ref \$struct eq "HASH") {
for \$item (sort keys %\$struct) {
print \$item," " if \$main;
printstruct(\$struct->{\$item});
print \$ret;
}
} else {
print \$struct,\$ret;
}
}

my \$struct={
mykey1 => { 'firstkey' => 'firstvalue', 'secondkey' => 'secondval'
+ },
mykey2 => { 'ninza'    => 'turtle',     'Hurricane' => 'Dennis' },
mykey3 => [ [ 'one', 'two', 'three' ] ],
mykey4 => [ [ 4, 5, 'three' ], [ 6, 7, 'four' ], [ 8, 9, 'five' ]
+],
};

printstruct(\$struct,1);
Note that I was unsure which the correct data struct was, so I made some changes in it as you can see. This would work for any struct with the three basic data types.

Re: Parsing complex data
by sh1tn (Priest) on Jul 15, 2005 at 15:56 UTC
```my @data = [
mykey1 => {firstkey => 'firstvalue', secondkey => 'secondval' },
mykey2 => {ninza => 'turtle', 'Hurricane' => 'Dennis'},
mykey3 => [ [one,two, three] ],
mykey4 => [ [4, 5, three], [6, 7, four], [8, 9, five] ],
];

for( @{\$data[0]} ){
ref or print "\$_ => " and next;
ref eq 'SCALAR' and print \$\$_ and next;
ref eq 'HASH'   and print join( ',', values %\$_ ), \$/;
ref eq 'ARRAY'  and do {
for( @{\$_} ){
print join( ',', split( '\s', "@\$_ " ))
}
print \$/
};
}