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

The Enlightened,

perl v5.8.8, use strict, use diagnostics

I hava an array of hashes that match to database fields

$customer->[0]{_name} $customer->[0]{_address1} $customer->[0]{_address2}
I would like to substitute the hash name with
my $i = 1; $varname = "_address" . $i; print "Customer Address", $customer->[0]{$varname};
for looping purposes, but it doesn't work.
print "Customer Address", $customer->[0]{${varname}};
does not work. I get the an uninitialized value error (for both tries).

I could put the hashes into address array and then loop through those but laziness makes me think perl can do it...

Thank you,

Replies are listed 'Best First'.
Re: Hash name variable substitution
by Errto (Vicar) on May 21, 2007 at 20:13 UTC
    The following works fine for me:
    $customer->[0]{_address1} = 'hello'; my $i = 1; my $varname = '_address' . $i; print $customer->[0]{$varname};
    prints "hello". Perhaps your issue lies elsewhere. If you can come up with a small runnable program that illustrates this error that may be more helpful.

      Thanks Errto,

      Sorry - the database field has no entry hence the uninitialized value. Choosing a populated field works fine. I will just take my slice of humbleberry pie for wasting the Enlightened's time...

Re: Hash name variable substitution
by thezip (Vicar) on May 21, 2007 at 20:28 UTC

    Hey peterb, are you looking for something like this?

    #!/perl/bin/perl -w use strict; use Data::Dumper; my $data = [ { _name => "John Smith", _address1 => "123 Foo St.", _address2 => "Apt 5", }, { _name => "Brigitte Nelson", _address1 => "150 Park Pl.", _address2 => "Suite 223", }, ]; my @cols = qw / _name _address1 _address2 /; for my $customer (@$data) { for my $col (@cols) { printf "%s => %s\n", $col, $customer->{$col} || "<empty>"; } }

    Updated: Added <empty> string in case of emptiness...


    Where do you want *them* to go today?
Re: Hash name variable substitution
by shmem (Chancellor) on May 21, 2007 at 20:33 UTC
    I would like to substitute the hash name with

    You don't have a hash name - which would mean you had named hashes - but hash keys in your array of anonymous hashes. If you change the key and reference that changed key, there's no value behind it - the value you are trying to acces is bound to the old (unchanged) key. To change a key, you have to copy over the value the old key is pointing at into the slot pointed at by the new key:

    my $i = 1; $varname = "_address" . $i; $customer->[0]{$varname} = $customer->[0]{'_address'}; print "Customer Address", $customer->[0]{$varname};

    But...

    $customer->[0]{_address1} $customer->[0]{_address2}

    whenever there are keys with a number attached, that cries for a revision of the data structure: store an anonymous array as the value to that hash. Then you have

    $customer->[0]{_address}[0] $customer->[0]{_address}[1]

    and looping becomes much easier:

    my $arrayref = $customer->[0]{_address}; for my $address (@$arrayref) { # do whatever with $address ... }

    But if you really have those column names (_address1,_addresss2,...,_adressn) in your tables, then the database design is flawed. You might want to normalize the addresses out to a another table.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}