perl - How to dig into an certain hash depth? -
i have hash don't know depth. got dbi::selectall_hashref second parameter given user.
so depending on query can have 2-levels hash.
hash_ref = ( aphrodite => ( foo => ( name => aphrodite, foobar => foo => 1, b => 2, ) bar => ( name => aphrodite, foobar => bar => 1, b => 2, ) ) apollo => ( ... ) ares => ( ... ) ) as can see key columns redundant hash. remove redundant keys.
if know 2-levels hash can solve problem this:
for $name (keys $hash_ref) { $foobar (keys $hash_ref->{$name}) { $h = $hash_ref->{$name}{$foobar}; delete $h->{name}; delete $h->{foobar}; } } however 3-levels hash need 3 cascaded for-loop , on.
how can dynamically remove redundant keys
$hash_refi.e.name,foobar?
my initial idea recursively iterate trough hash:
iterate($hash_ref, scalar @keys); sub iterate { ($ref, $depth) = @_; for(keys $ref) { if ($depth > 0) { iterate($ref->{$_}, $depth - 1); } else { delete $ref->{$_} for(@keys); } } } it works it's ugly, ugly... before going further know if missed something. perhaps solution simpler think.
any ideas?
more details?
i writing database fetcher takes user configuration contains sql query $sql , hash keys @keys. values database with:
$dbh->selecthall_hashref($sql, \@keys, {}, @bind); i have clean fetched data according additional. apply these rules, have iterate deepest level of $hash_ref access keys/values.
i think need. recurses through hash until finds layer hash values aren't references. removes elements layer keys in @keys
use strict; use warnings; use 5.010; use data::dump; use list::util 'any'; $hash_ref = { aphrodite => { bar => { name => "aphrodite", foobar => "bar", => 3, b => 4, }, foo => { name => "aphrodite", foobar => "foo", => 1, b => 2, }, }, apollo => { bar => { name => "apollo", foobar => "bar", => 7, b => 8, }, foo => { name => "apollo", foobar => "foo", => 5, b => 6, }, }, ares => { bar => { name => "ares", foobar => "bar", => 11, b => 12, }, foo => { name => "ares", foobar => "foo", => 9, b => 10, }, }, }; @keys = qw/ name foobar /; remove_dups($hash_ref, \@keys); dd $hash_ref; sub remove_dups { ($href, $keys) = @_; if ( { ref } values %$href ) { remove_dups($_, $keys) values %$href; } else { delete @{$href}{@$keys}; } } output
{ aphrodite => { bar => { => 3, b => 4 }, foo => { => 1, b => 2 } }, apollo => { bar => { => 7, b => 8 }, foo => { => 5, b => 6 } }, ares => { bar => { => 11, b => 12 }, foo => { => 9, b => 10 } }, }
Comments
Post a Comment