What is the Python equivalent of the Perl "..
" (range, or flip-flop) operator?
for ( qw( foo bar barbar baz bazbaz bletch ) ) {
print "$_\n" if /ar.a/ .. /az\w/;
}
Output:
barbar
baz
bazbaz
The Python workaround that I am aware of includes generator expression and indexing with the help of enumerate
, but this seems cumbersome:
import re
lst = 'foo bar barbar baz bazbaz bletch'.split()
idx_from = list(i for i, el in enumerate(lst) if re.search(r'ar.a', el))[0]
idx_to = list(i for i, el in enumerate(lst) if re.search(r'az\w', el))[0]
lst_subset = lst[ idx_from : (idx_to+1)]
print(lst_subset)
# ['barbar', 'baz', 'bazbaz']
I am looking for just one range. There is currently no need to have multiple ranges.
When the operands aren't simple numbers, EXPR1 .. EXPR2
in scalar context is equivalent to following (except for the scope created by do { }
):
do {
state $hidden_state = 0;
if ( $hidden_state ) {
++$hidden_state;
} else {
$hidden_state = 1 if EXPR1;
}
my $rv = $hidden_state;
# Or `$hidden_state > 1 && EXPR2` for `...`.
if ( $hidden_state && EXPR2 ) {
$rv .= "E0";
$hidden_state = 0;
}
$rv
}
Since you only care whether the flip-flop returns true or false, the above simplifies to the following:
do {
state $hidden_state = false;
$hidden_state ||= EXPR1;
my $rv = $hidden_state;
$hidden_state &&= EXPR2;
$rv
}
Now we have to translate this. Since the flip-flip is usually used as a generator, that's what I'll create.
def flipflop( enumerable, start_cond, end_cond ):
state = False
for val in enumerable:
if not state:
state = start_cond( val )
if state:
yield val
if state:
state = end_cond( val )
import re
lst = 'foo bar barbar baz bazbaz bletch'.split()
for x in flipflop( lst, lambda v: re.search( r'ar.a', v ), lambda v: re.search( r'az\w', v ) ):
print( x )