Re: flip-flop operator and sequence number
by chipmunk (Parson) on Jun 28, 2001 at 18:02 UTC
|
The return value from the flip-flop operator (in scalar context) actually gives you the info you need to skip the first and last values matched.
When the flip-flop operator in scalar 'flips' (when the left hand side is true), it starts at 1 and counts up until it 'flops' (when the right hand side is true). So, skip to the next element when the return value equals 1.
Also, when the flip-flop operator 'flops', it appends 'E0' to the return value. For example, if it finds five matches in a row, it will return (1, 2, 3, 4, '5E0'). So, you should also skip to the next element when the return value contains an E.
Here's how this might be coded:
foreach (@data){
next unless $check = /start/ .. /stop/;
next if $check == '1' or $check =~ /E/;
# do stuff
}
| [reply] [d/l] |
Re: flip-flop operator and sequence number
by merlyn (Sage) on Jun 28, 2001 at 18:23 UTC
|
foreach (grep { not (/start/../stop/) =~ /^1?$|E/ } @data) {
..
}
-- Randal L. Schwartz, Perl hacker | [reply] [d/l] |
|
foreach (sub {pop;shift;@_}->(grep /start/../stop/, @data) ) {
...
}
Sorry, just kidding :-)
UPDATE: taking Abigail and John M. Dlugosz's remarks into account, the original post wanted to stop after the first occurence of 'stop'. I guess we should then be using ?? instead of // to prevent matching more than once. foreach (sub {pop;shift;@_}->(grep ?start?..?stop?, @data) ) {
...
}
--bwana147 | [reply] [d/l] [select] |
|
That code doesn't do the same.
#!/opt/perl/bin/perl -wl
use strict;
my @data = qw /foo start bar baz stop qux
start quux stop fuzzle/;
foreach (grep /start/ .. /stop/, @data) {
next if /start/ || /stop/;
print
}
print "----";
foreach (sub {pop; shift; @_} ->
(grep /start/ .. /stop/, @data)) {
print;
}
__END__
bar
baz
quux
----
bar
baz
stop
start
quux
You are losing the boundaries of the flip-flop operator,
and use the boundaries of grep. But those
boundary events are not necessarely the same.
-- Abigail | [reply] [d/l] [select] |
|
|
I love it! Using the sub{}->() idiom you can modify a list in-place without using a temporary. Your code does the same as:
my @temp= grep /start/../stop/, @data;
pop @temp;
shift @temp;
foreach (@temp) { ... }
right?
—John | [reply] [d/l] [select] |
|
|
|
.. not being able to do, reduced to nitpicking.
Sorry your answer was so beautiful I studied it but..
perl -e '@data=qw(1 2 3 4 5 6 7 8 9 10 11);
foreach (grep {not (/1/../3/) =~ /^1?$|E/ } @data) {
print "o> $_\n";
}
'
prints
o> 2
o> 11
I hope I'm wrong.. | [reply] [d/l] |
|
Thats looks like the correct output to me. What were you
expecting to see?
Update: Ok. Getting downvotes, so perhaps I'll be
a little clearer.
Your array contains the numbers from 1 to 11. Your
flip-flop condition is /1/ .. /3/. These are regular
expressions and match if the values they are matched against
contain this string in any position. Obviously it
switches on when it gets to 1 and switches off when it
gets to three. It then switches on again when it gets to
10. It would have switched off again had your array gone up
to 13.
The problem is therefore not with merlyn's algorithm,
but with your implementation of it :)
--
<http://www.dave.org.uk>
Perl Training in the UK <http://www.iterative-software.com>
| [reply] |
|
foreach ( grep { (/start/../stop/) !~ /^1?$|E/} @arry ){
#...
}
I looked a bit further, and what is coming out of the (/start/../stop/) is the sequence number...until you put the not in front of it. Then it just yields blank or 1!
Any ideas why? Is it being evaluated in list context? Why does the not have any influence on the context?
--
iakobski | [reply] [d/l] [select] |
|
Uh, it is working. The start match is /1/, which also triggers on "10".
So the output is:
1 start - don't show
2 in - show
3 end - don't show
4 out
5 out
6 out
7 out
8 out
9 out
10 start - don't show
11 in - show
It's exactly right. My solution works fine, no need to modify it.
-- Randal L. Schwartz, Perl hacker | [reply] [d/l] |
|
|
|
| [reply] |
|
That's a good observation on what not does.
But, the binding operator =~ has a higher order of precidence, so the not applies to the result of the match, not to the left hand side being matched.
—John
| [reply] [d/l] [select] |
Re: flip-flop operator and sequence number
by bwana147 (Pilgrim) on Jun 28, 2001 at 18:00 UTC
|
To use the sequence counter, I guess you'd use something like this:
foreach ( @data ) {
my $seq = /start/ .. /stop/;
next unless $seq > 1 && substr($seq, -2) ne 'E0';
# do_stuff
}
Not tested, but you get the idea... --bwana147 | [reply] [d/l] |
Re: flip-flop operator and sequence number
by Fool on the Hill (Acolyte) on Jun 28, 2001 at 18:25 UTC
|
Hello,
You can put real code into the grep so that it looks this this. That way you can access the sequence number you are refering to. The sequence counter is not visible because grep just uses whether the block evaluates to true or false for the list value (I think!)
#!/usr/bin/perl -w
use strict;
my @data=(<DATA>);
foreach (grep { my $sequence_number=/START/ .. /STOP/; $sequence_numbe
+r ne 1 and $sequence_number !~ /E0/ and $sequence_number;} @data ) {
chomp;
print "$_ Between START and STOP\n";
}
__END__
START
Sausage
Mash
Mushy Peas
STOP
Monkey Nuts
START
Bananas
Custard
STOP
Tarzan
| [reply] [d/l] |
Re: flip-flop operator and sequence number
by John M. Dlugosz (Monsignor) on Jun 28, 2001 at 19:02 UTC
|
I don't like the idea of copying chunks of code either.
I notice you already got answers on how to tell when it flips or filter out the first/last without retesting, but I wanted to make a note on this specific point of repreating the RE.
my $start= qr/start/; # note the regex's once
my $stop= qr/stop/;
foreach (grep /$start/ .. /$stop/, @data) {
next if /$start/;
last if /$stop/;
# ....
| [reply] [d/l] |
Re: flip-flop operator and sequence number
by mattr (Curate) on Jun 28, 2001 at 18:14 UTC
|
# variation with grep
@a=qw(abc def ghi jkl mno pqr stu vwxyz);
@g = grep /i/../u/, @a;
for (1..$#g-1) {
print "$g[$_]\n";
}
# with map
@a=qw(abc def ghi jkl mno pqr stu vwxyz);
$flag=-1;
sub go {
print "$_\n" if ($flag>0);
if ($_ =~ /i|u/) {
$flag = $flag * -1
}
}
@g = map{ &go($_) => $_ } @a;
Just checked, it does not work if you say
qw(abc start some things to print stop vwxyz) and look
for start|stop but maybe that's not how you're using it. Does
seem to work (checked the grep version) for
qw(abc def start ghi jkl xxx mno pqr stu stop vwxyz).
Updated: You guys are so right. Kudos and votes to you. | [reply] [d/l] |
Re: flip-flop operator and sequence number
by gaudior (Pilgrim) on Jun 28, 2001 at 23:54 UTC
|
| [reply] |