Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

how to avoid nested looping?

by lamp (Chaplain)
on Feb 04, 2005 at 06:01 UTC ( #427942=perlquestion: print w/ replies, xml ) Need Help??
lamp has asked for the wisdom of the Perl Monks concerning the following question:

The following is the format which i am getting from
'$testsub->result()' method using Data::Dumper.
$VAR1 = [ { 'columns' => [ { 'test' => '87588', 'test1' => '87588', 'test2' => '0' }, { 'test' => '87588', 'test1' => '87588', 'test2' => '0' }, ] } ];
and i am using the following code to get the total
value of 'test1'.
map { map{ $total_value += $_->{test1} ; } @{$_->{columns}}; } @{$testsub->result()}; }
Is there any method to avoid double looping?.

Comment on how to avoid nested looping?
Select or Download Code
Re: how to avoid nested looping?
by bgreenlee (Friar) on Feb 04, 2005 at 06:18 UTC

    If $testsub->result() always only returns a list ref with one value, like in your example, you can certainly avoid two loops (just loop on @{$testsub->results()->[0]->{columns}}); otherwise, no.

    BTW, I'm not a huge fan of using map in a void context (i.e. you're not using map to 'map' one list to another). Sometimes it's clearer to just do it the old fashioned way:

    my $total_value = 0; foreach my $result (@{$testsub->result()}) { foreach my $column (@{$result->{columns}}) { $total_value += $column->{test1}; } }

    -b

      Side note: map in void context no longer carries the overhead that it did and, in any event, if you must apply the same behavior to every element in a list, many programmers find using map is often clearer than foreach. Sometimes it's just a stylistic thing.

      Of course, you point out that the word "map" can be misleading, but if one merely thinks of the word "apply" or something else in place of map, it makes more sense. After all, Lisp programmers have gotten along with lambda for many years. (Not to mention car and cdr!)

      Cheers,
      Ovid

      New address of my CGI Course.

        For me it's more a matter of clarity/readability for someone looking over my code, particularly with nested maps like this (do you really find map { map { ... } @bar } @foo easier to mentally parse than foreach (@foo) { foreach (@bar) { ... } }?). But, you're right...it's mostly a stylistic thing and this is a classic example of TMTOWTDI.

        Update: I tried a little test and foreach was actually significantly faster (for this particular test, that is):

        #!perl -w use strict; use Benchmark; Benchmark::cmpthese(-5, { 'foreach' => sub { my $sum=0; foreach (1..100) { foreach (1..100) +{ $sum++ }}}, 'map' => sub {my $sum=0; map { map { $sum++ } (1..100) } (1..100) +}, });
        ------------------------------ Rate map foreach map 345/s -- -43% foreach 603/s 75% --

        What gives?

        -b

Re: how to avoid nested looping?
by davido (Archbishop) on Feb 04, 2005 at 06:39 UTC

    In order to sum up all the leaves of a nested datastructure, you have to look at each and every leaf. This means nested iteration, or in other words, nested looping. Yes, you can hide the looping in recursion, but it's still looping, in a different way. There's no way of getting around the fact that you have to inspect each leaf.

    Perhaps you could avoid this step by keeping a running total as you accumulate the leaves into the nested structure. I don't know where you're getting the data that fills this datastructure, but if you find it expensive (from a computational standpoint) to wend your way through the datastructure adding its nodes, try looking at the problem in a way that avoids having to do that. If you can keep a running tally, you save yourself from the looping, at the expense of a little computational work each time you add, remove, or modify an element in the structure.


    Dave

Re: how to avoid nested looping?
by dimar (Curate) on Feb 04, 2005 at 08:27 UTC

    Unless I am missing something amidst all this talk of map and leaves (like the forest for the trees), there is no reason why you cannot simply specify the exact address of the data element that you want to retrieve.

    map{$total_value+=$_->{test1}}@{$testsub->result()->[0]->{columns}}

    Off the top of my head this syntax may be wrong, gotta get on the other machine to check it.

    Update: I did miss something, already answered.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://427942]
Front-paged by davidj
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (15)
As of 2014-09-22 18:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (198 votes), past polls