我正在编写一个收集指标的python脚本,我有:
collected
,包含所有消息的列表,存储为词典denied_metrics
,包含所有已编译正则表达式的列表我希望能够禁止转发collected[i]['service']
与denied_metrics
中至少一个正则表达式匹配的邮件。
我尝试使用列表理解和filter
来实现我的目标,但我没有设法做到这一点。
鉴于消息具有以下结构:
msg = {
'service': 'foo',
'metric': 1.0,
'denied': False
}
实际上我正在过滤所有collected
条消息,如下所示
def filter_denied( denied_metrics, collected ):
for pattern in denied_metrics:
for msg in collected
if pattern.match( msg['service'] ):
msg['denied'] = True
return [ msg for msg in collected if msg['denied'] is not True ]
是否有(更好的?)方法来仅使用列表理解和filter
或{{1}的组合来获取允许的消息列表}?
我不知道有可能像@eyquem在他的回答中所说的那样处理这个问题。
答案 0 :(得分:2)
IIUC,我可能会做类似
的事情allowed = [msg for msg in collected
if not any( dm.search(msg['service'])
for dm in denied_metrics) ]
例如:
>>> pprint.pprint(collected)
[{'denied': False, 'metric': 1.0, 'service': 'ab'},
{'denied': False, 'metric': 1.0, 'service': 'bc'},
{'denied': False, 'metric': 1.0, 'service': 'ca'},
{'denied': False, 'metric': 1.0, 'service': 'cb'},
{'denied': False, 'metric': 1.0, 'service': 'bc'}]
>>> denied_metrics = [re.compile("a"), re.compile("c$")]
>>> allowed = [msg for msg in collected
if not any(dm.search(msg['service'])
for dm in denied_metrics)]
>>> allowed
[{'metric': 1.0, 'service': 'cb', 'denied': False}]
当然,您需要search
还是match
取决于您的正则表达式。 [顺便说一句,不会'denied_services'是一个更好的名字?]
答案 1 :(得分:1)
你有XY problem。
以下是两种在迭代中删除列表元素的方法:
li = ['a',12,45,'h',56,'ju',0]
print li
for i in xrange(len(li)-1,-1,-1):
if isinstance(li[i],int):
del li[i]
print li
# prints ['a', 'h', 'ju']
li = ['a',12,45,'h',56,'ju',0]
L = len(li)
for i,x in enumerate(reversed(li),1):
if isinstance(x,str):
del li[L-i]
print li
# prints [12, 45, 56, 0]
在最后一个代码reversed()
中返回一个迭代器,不需要创建新列表。