in reply to Re: A more elegant way to filter a nested hash?
in thread A more elegant way to filter a nested hash?
map can't handle recursion.
Of course you can have a map block inside a function, and recurse into that from inside the map block:
sub hash_filter { my $source = shift; my $filter = shift; return { map { ref $filter->{$_} eq 'HASH' ? ref $source->{$_} eq 'HASH' ? ($_, hash_filter( $source->{$_}, $filter->{$_} )) : croak "bad filter: on '$_', expected HASH\n" : ($_, $source->{$_}) } grep { exists $source->{$_} } keys %$filter } }
which btw is the for loop of the OP rewritten in terms of map/grep.
update: a terse version which eliminates shifting @_ and working directly on the arguments (which aren't altered by the function):
sub hash_filter { return { map { ref $_[1]->{$_} eq 'HASH' ? ref $_[0]->{$_} eq 'HASH' ? ($_, hash_filter( $_[0]->{$_}, $_[1]->{$_} )) : croak "bad filter: on '$_', expected HASH\n" : ($_, $_[0]->{$_}) } grep { exists $_[0]->{$_} } keys %{$_[1]} } }
Now that's arguably micro-optimized and far less readable (11 lines) than the OP's code (18 lines) imho.
More elegant? Perhaps for those who prefer nested ?: statements for simple expressions over if/else blocks...
update 2: B::Concise shows identical optrees (execpt line numbers) for the "for" and "map/grep" solutions.
|
---|
Replies are listed 'Best First'. | |
---|---|
Re^3: A more elegant way to filter a nested hash?
by jimpudar (Pilgrim) on May 31, 2018 at 20:41 UTC |