in reply to processing a list of events

You could write it as two iterators; one that returns the index of the next "A" event each time it's called, and one that returns the index of each "B" event each time it's called:

use strict; use warnings; use List::Util 'first'; my @ary = qw/EVENT_A EVENT_A EVENT_B EVENT_A EVENT_B EVENT_B/; my($a_it, $b_it) = map{ my $w = "EVENT_$_"; mk_it(\@ary, sub{ shift eq $w }) } qw/A + B/; while( defined(my $eva = $a_it->()) ) { my $evb = $b_it->(); die "A/B event mismatch for $ary[$eva]" unless defined $evb && $ev +b>$eva; print "$ary[$eva]($eva) => $ary[$evb]($evb)\n"; } sub mk_it { my($pos, $aref, $wanted) = (0, @_); sub { my $rv = first{$wanted->($aref->[$_])} $pos..$#$aref; $pos = defined $rv ? $rv+1 : $pos+1; $rv; } }

Update: Found the time to present actual code (not pseudo-code).


Dave

Replies are listed 'Best First'.
Re^2: processing a list of events
by Laurent_R (Canon) on Apr 30, 2015 at 22:36 UTC
    I was also thinking about iterators, I like the idea and I have written quite a number of them over the last years. Here, however, I would tend to prefer only one iterator that would keep a buffer of the unused A values and return a pair of A and B values when needed.

    The following was written directly at the command line and is not an iterator (in the sense that it is not a subroutine returning the next relevant element), but it is iterating only once over the input data and it would be simple to put that code into an iterator closure that would keep track of the A buffer and return the A and the B values on demand:

    $ perl -e ' > use strict; > use warnings; > my @in = split /\n/, > "a 123 > a 125 > b 127 > a 129 > a 130 > b 131 > a 132 > b 133"; > > my @a_buff; > for (@in) { > push @a_buff, $_ and next if /a/; > my $aa = shift @a_buff; # avoid to use the $a special variable > my $diff = $2 - $1 if "$aa - $_" =~ /(\d+)[^\d]*(\d+)/; > print "$aa ; $_ => $diff\n"; > } > ' a 123 ; b 127 => 4 a 125 ; b 131 => 6 a 129 ; b 133 => 4
    Update: I have now done a full-fledged iterator as a closure:
    use strict; use warnings; my $iter = create_iter(); while (my ($aa, $bb) = $iter->()) { last unless defined $bb; my $diff = $2 - $1 if "$aa $bb" =~ /(\d+)[^\d]*(\d+)/; print "$aa ; $bb => $diff\n"; } sub create_iter { my @a_buff; return sub { while (<DATA>){ chomp; push @a_buff, $_ and next if /a/; return shift @a_buff, $_; } } } __DATA__ a 123 a 125 b 127 a 129 a 130 b 131 a 132 b 133
    And this prints the same result:
    $ perl iter_pairs.pl a 123 ; b 127 => 4 a 125 ; b 131 => 6 a 129 ; b 133 => 4
    Update 2: the same using a state variable (we are stuck with old versions of Perl at work, so I sometimes don't think about such relatively new features which, in this case, make the code a bit simpler than a closure):
    use strict; use warnings; use feature "state"; while (my ($aa, $bb) = iter()) { last unless defined $bb; my $diff = $2 - $1 if "$aa $bb" =~ /(\d+)[^\d]*(\d+)/; print "$aa ; $bb => $diff\n"; } sub iter { state @a_buff; while (<DATA>){ chomp; push @a_buff, $_ and next if /a/; return shift @a_buff, $_; } } __DATA__ a 123 ...

    Je suis Charlie.