1

I have a sql wherein I am fetching few records, sorted by full name.

My requirement is to extract chunks of similar names and then do some operation on it.

Say, the sql returns some records containing names like [name1,name1,name2,name3,name3]

I need to split them to [name1,name1] , [name2] , [name3,name3]

I am able to do it, but I am not happy with my implementation as I have to call doSomethingWithNames()twice.

while (my $paRecs = $pStatementHandle->fetchall_arrayref({}, 3)){
   foreach my $phRec(@{$paRecs}){
       my $pCurrentName = $phRec->{'FULL_NAME'};
       if ((scalar(@aParentRecords) eq 0) or ($aParentRecords[-1] eq $pCurrentName)){
           push(@aParentRecords, $pCurrentName);
       } else {
           doSomethingWithNames(\@aParentRecords);
           @aParentRecords= ();
           push(@aParentRecords, $pCurrentName);
       }
   }
};
doSomethingWithNames(\@aParentRecords); # This should be inside while loop  

I believe am running into this issue because while doesn't go into the loop for the last iteration as fetch* returns undef.

Sounds basic PERL stuff, but tried many loop constructs with no luck. Any pointer will be a great help

Soumya
  • 885
  • 3
  • 14
  • 29
  • Tip: The name of the language is "Perl", not "PERL". It's not an acronym. – ikegami Aug 25 '19 at 07:17
  • Tip: `eq` is for comparing strings. Use `==` to compare numbers. – ikegami Aug 25 '19 at 07:17
  • Tip: There's no point in putting `a` in front of array names. – ikegami Aug 25 '19 at 07:18
  • Tip: The final `doSomethingWithNames(\@aParentRecords);` should be `doSomethingWithNames(\@aParentRecords) if @aParentRecords;` (for when there are no records to fetch). – ikegami Aug 25 '19 at 07:55
  • Tip: Only use `and` and `or` when followed by `return`, `die`, `next`, `last` or some other flow-control operator. Use `&&` and `||` elsewhere. – ikegami Aug 25 '19 at 08:00

1 Answers1

1

The trick is to postpone existing the loop by converting it into an infinite loop. This requires checking the loop-terminating condition (!$rows) twice, though.

my $rows = [];
my $prev_name = '';
my @group;
while (1) {
   $rows = $sth->fetchall_arrayref({}, 3) if !@$rows;

   if (!$rows || $rows->[0]->{FULL_NAME} ne $prev_name)
      if (@group) {
         do_something(\@group);
         @group = ();
      }

      last if !$rows;
   }

   $prev_name = $rows->[0]->{FULL_NAME};
   push @group, shift(@$rows);
}
ikegami
  • 367,544
  • 15
  • 269
  • 518