Perl“
..
”(范围或触发器)运算符的 Python 等价物是什么?
for ( qw( foo bar barbar baz bazbaz bletch ) ) {
print "$_\n" if /ar.a/ .. /az\w/;
}
输出:
barbar
baz
bazbaz
我所知道的Python解决方法包括生成器表达式和借助
enumerate
的帮助进行索引,但这似乎很麻烦:
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']
我只寻找一个范围。目前不需要有多个范围。
基本(在线尝试!):
import re
in_range = False
for word in 'foo bar barbar baz bazbaz bletch'.split():
if not in_range:
in_range = re.search(r'ar.a', word)
if in_range:
print(word)
if in_range:
in_range = not re.search(r'az\w', word)
通过课程(在线尝试!):
import re
class Within:
def __init__(self, flip, flop):
self.flip = flip
self.flop = flop
self.state = False
def __bool__(self):
if not self.state and self.flip():
self.state = True
result = self.state
if self.state and self.flop():
self.state = False
return result
within = Within(
lambda: re.search(r'ar.a', word),
lambda: re.search(r'az\w', word),
)
for word in 'foo bar barbar baz bazbaz bletch'.split():
if within:
print(word)
Itertoolsish(在线尝试!):
import re
def flipflop(iterable, flip, flop):
state = False
for x in iterable:
if not state:
state = flip(x)
if state:
yield x
if state:
state = not flop(x)
for word in flipflop(
'foo bar barbar baz bazbaz bletch'.split(),
re.compile(r'ar.a').search,
re.compile(r'az\w').search
):
print(word)
或者没有状态变量,外循环搜索元素以进入范围,内循环搜索元素以退出范围(在线尝试!):
import re
def flipflop(iterable, enter, exit):
it = iter(iterable)
for x in it:
if enter(x):
yield x
if not exit(x):
for x in it:
yield x
if exit(x):
break
for word in flipflop(
'foo bar barbar baz bazbaz bletch'.split(),
re.compile(r'ar.a').search,
re.compile(r'az\w').search
):
print(word)
警告,因为我不知道
perl
足以理解什么..
,我实现了类似于GNU AWK
的Ranges的东西,希望它足够接近您的用例。
据了解,没有直接等效的可用方法,因此我建议使用以下标记方式来实现此功能
import re
def get_re_range(iterable, start_pattern, end_pattern):
flag = False
for element in iterable:
if re.search(start_pattern, element):
flag = True
if flag:
yield element
if re.search(end_pattern, element):
flag = False
words = "foo bar barbar baz bazbaz bletch".split()
for word in get_re_range(words, r'ar.a', r'az\w'):
print(word)
提供输出
barbar
baz
bazbaz
观察
if
的顺序以获得包容性行为。
当操作数不是简单数字时,标量上下文中的
EXPR1 .. EXPR2
相当于以下内容(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
}
由于您只关心触发器返回 true 或 false,因此上面的内容简化为以下内容:
do {
state $hidden_state = false;
$hidden_state ||= EXPR1;
my $rv = $hidden_state;
$hidden_state &&= EXPR2;
$rv
}
现在我们必须翻译这个。由于翻转翻转通常用作生成器,这就是我将创建的。
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 )