Swechsler
Swechsler

Reputation: 1

Perl: Build a hash without a predefined number of key columns?

I'm trying to write a function that will read a delimited file (think something like /etc/passwd) and return the values in a hash. The delimiter, column names and key columns will be specified as parameters to the function, the last two passed as array references. It will return a reference to a hash.

I'd like to allow both single and compound keys, but I can't figure out the best way to create the hash when I don't know the depth of the keys beforehand.

For example, suppose I specify 4 columns: A, B, C, and D, and two key columns: A and D. To assign values from a single line in the file, we'd have something like:

$var->{A value)->{D value)->{A} = A value;
$var->{A value)->{D value)->{B} = B value;
...

However, if I specify only a single key column (B), it would look like:

$var->{B value)->{A} = A value;
$var->{B value)->{B} = B value;
...

What would be a way to generalize this without knowing the number of key columns prior to execution?

Upvotes: 0

Views: 89

Answers (1)

ikegami
ikegami

Reputation: 385809

use Data::Diver qw( DiveVal );

my @key_col_names = ...;
my @col_names     = ...;

my $data;
while ( my @row = ... ) {
    my %rec; @rec{@col_names} = @row;
    my @keys = @rec{@key_col_names};
    DiveVal($data, map \$_, @keys) = \%rec;
}

You can use the following instead of DiveVal($data, map \$_, @keys) = \%rec:

sub dive_val :lvalue {
   my $p = \shift;
   $p = \( $$p->{$_} ) for @_;
   $$p
}

dive_val($data, @keys) = \%rec;

Upvotes: 1

Related Questions