I'm asking for advice on style, rather than how to solve a problem. How a professional would do it? What's readable to others -- and myself, in a year? So, all answers are maybe just opinion based and are welcome :-).
There's usual complex data structure AoHoAH... , not very deep. We can assume root is
$root = { value => [ ... ]};
Two types of array elements are "interesting":
{ type => 'items', value => [ ... ]} # and other key-value pairs { type => 'foo', value => { ... }} # and other key-value pairs
"Items" hash "points to" another array and is to be processed recursively. "Foo" hash is to be checked and may be replaced (split) with several hashes. Other "uninteresting" elements can be anything (but always hashrefs) and are to be left "as is".
The next sub is to be called as foobar( $root ), and hopefully will do everything right:
sub foobar { my $href = shift; $href-> { value } = [ map { foobar( $_ ) if $_-> { type } eq 'items'; $_-> { type } eq 'foo' ? SPLIT_FOO( $_ ) : $_ } @{ $href-> { value }}]; }
Or even shorter, moving a check out of sight:
sub foobaz { my $href = shift; $href-> { value } = [ map { foobar( $_ ) if $_-> { type } eq 'items'; SPLIT_IF_FOO( $_ ) } @{ $href-> { value }}]; }
The next sub has slightly less "punctuation noise" and skips assignment, and is to be called fooqux( $root-> { value }), i.e. now arrayref can serve as "root" instead of structure above.
sub fooqux { $aref = shift; splice @$aref, 0, @$aref, map { fooqux( $_-> { value }) if $_-> { type } eq 'items'; SPLIT_IF_FOO( $_ ) } @$aref }
What I'm not sure about all these, is they always rebuild any array within original structure, even if there's no "foo" elements at all. With condition checking moved to SPLIT, the SPLIT_IF_FOO is always called for all elements, regardless. Next sub prevents these shortcomings, but uses Perl's "no-no" -- the C-style loop.
sub fooquux { $aref = shift; for ( my $i = 0; $i < @$aref; $i ++ ) { my $item = $aref-> [ $i ]; fooquux( $item-> { value }) if $item-> { type } eq 'items'; next unless $item-> { type } eq 'foo'; my @list = SPLIT_FOO( $item ); splice @$aref, $i, 1, @list; $i += $#list } }
And, not sure what's worse, to splice potentially many times or to always replace with new array. Or maybe there's "best" idiomatic way to solve such problem?
In reply to To splice or not to splice? What implementation is more readable, efficient, etc.? by vr
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |