in reply to Hash of arrays of arrays

Note: I don't know anything about NDMB_File, so I'm working with the structure you showed.

For starters, Data::Dump is your debugging friend here:

use Data::Dumper; print(Dumper(\%db));

To move around your structure, have a look at these two snippets:

foreach $key (keys(%db)) { for ($record_num=0; $record_num<@{$db{$key}}; $record_num++) { foreach $field (@{$db{$key}[$record_num]}) { printf("Record %d of %s is %s.\n", $record_num, $key, $field, ); } } }
foreach $key (keys(%db)) { foreach $record (@{$db{$key}}) { foreach $field (@$record) { ... } } }

To append a record to a given key,

# From ref to array of fields: push(@{$db{$key}}, $record); -or- # From individual fields: push(@{$db{$key}}, [ $field1, $field2, $field3, $field4 ]); -or- # From a my'd array of fields: { my @fields = ...; push(@{$db{$key}}, \@fields); } -or- # From a array of fields that will change: push(@{$db{$key}}, [ @fields ]);

Comma-delimited:

# Gives: # key1,field1,field2,field3,field4 # key1,field1,field2,field3,field4 # key1,field1,field2,field3,field4 # key2,field1,field2,field3,field4 # key3,field1,field2,field3,field4 # key3,field1,field2,field3,field4 # # Doesn't handle commas in key or field. $,=','; $\=$/; foreach $key (keys(%db)) { foreach $record (@{$db{$key}}) { print $key, @$record; } } -or- # Gives: # key1,0,field1,field2,field3,field4 # key1,1,field1,field2,field3,field4 # key1,2,field1,field2,field3,field4 # key2,0,field1,field2,field3,field4 # key3,0,field1,field2,field3,field4 # key3,1,field1,field2,field3,field4 # # Doesn't handle commas in key or field. $,=','; $\=$/; foreach $key (keys(%db)) { for ($record_num=0; $record_num<@{$db{$key}}; $record_num++) { print $key, $record_num, @{$db{$key}[$record_num]}; } }

Replies are listed 'Best First'.
Re^2: Hash of arrays of arrays
by Anonymous Monk on Oct 08, 2004 at 18:08 UTC
    Many thanks to all who contributed in answer to my query - with the help of the Perl Monks, I am now most of the way there (though I had to dump the database idea in favour of a flat file - such is life!).

    However, I do have one small puzzle remaining, which perhaps someone could help me with:

    In one place, I need to add another record to my array of records, but only after checking all other records associated with that key, to make sure that the record I am adding is not a duplicate.

    So I need to test if I am at the end of the array, by checking a counter variable against the number of elements in the records array for the current key. I would have thought that the correct code would be along the lines of:
    if ($i < @{$db{$key}}) ...
    This is similar to the 'for' loop in ikegami's excellent example code. And I have seen something similar used in other code samples concerning hash-of-arrays structures. But when I print out the value of '@{$db{$key}}', I get:
    ARRAY(0xfdb30)
    Obviously, I would have expected to get an integer. Does the fact that my array elements contain another level of arrays (unlike the other examples I have seen) mean that I need a different test? Or is this simply a side-effect of 'print'?

    Can I rely on using '@{$db{$key}}' in my test, or would anyone like to suggest something different??

    Thanks in advance for any further guidance you can give me!

    Graham Scott.

      Compare:

      $\=$/; @a = qw( d e f ); print(@a); # prints 'def' print(scalar(@a)); # prints '3' print(@a==3?'3':'!3'); # prints '3'

      print accepts a list as an argument. @array returns a list of its elements in a list context.

      < accepts scalars as arguments. @array returns the number of elements it has in a scalar context.

      So yes, you can rely on @{$db{$key}} for your test. If you want to make it clear to yourself, use scalar(@{$db{$key}}) instead.