Re: Re: flip-flop operator and sequence number
by bwana147 (Pilgrim) on Jun 28, 2001 at 18:38 UTC
|
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] |
|
That's a good point. But your code is not the same either, since his original said last not next. He was stopping after the first group and ignoring a subsequent /start/.
| [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] |
|
Er, actually, I feel like a hobbit being caught red handed meddling in the affairs of wizards, which are, as everybody knows, subtle and quick to anger.
I tried and fiddle a bit with this and it's somewhat interesting. @_ is not itself aliased with the list of arguments. But each element of @_ is individually aliased with each argument. That means that you can't change the list itself (i.e. the number of its elements), but you can the values of each element. If I do:
sub { pop; shift; }->(@array);
It'll leave @array unharmed. OTOH, if I do: sub { $_[0] = 'whatever' }->(@array);
It will change the first element of @array. You can combine both (although I would not recommend it): sub { shift; $_[0] = 'whatever' }->(@array);
# changes the *second* element of @array
--bwana147 | [reply] [d/l] [select] |
|
Re: Re: flip-flop operator and sequence number
by mattr (Curate) on Jun 28, 2001 at 19:03 UTC
|
.. 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] |
Re: Re: flip-flop operator and sequence number
by iakobski (Pilgrim) on Jun 28, 2001 at 19:13 UTC
|
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] |
|
[danger:jandrew:~]$ cat blah.pl
#!/usr/bin/perl -w
use strict;
my @data = qw/one start two three stop four/;
foreach (grep {not (/^start/../^stop/) =~ /^1?$|E/ } @data) {
print "o> $_\n";
}
[danger:jandrew:~]$ perl5.00503 blah.pl
o> two
o> three
[danger:jandrew:~]$ perl5.6.1 blah.pl
o> one
o> start
o> two
o> three
o> stop
o> four
Because, in 5.6+, the not operator with parens acts like a function
(returns the negation of what's in the parens), so you'd want another
set of parens to properly delimit what we want to negate (or use a
unary +):
my @data = qw/one start two three stop four/;
foreach (grep {not ((/^start/../^stop/) =~ /^1?$|E/) } @data) {
print "o> $_\n";
}
# or:
my @data = qw/one start two three stop four/;
foreach (grep {not +(/^start/../^stop/) =~ /^1?$|E/ } @data) {
print "o> $_\n";
}
| [reply] [d/l] [select] |
|
|
| [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] |