0

我正在编写一个收集指标的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 ]

问题

是否有一种(更好的?)方法来获取允许的消息列表,仅使用列表理解filteror的组合reduce


编辑

我不知道像@eyquem 在他的回答中建议的那样解决问题的可能性。

4

2 回答 2

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}]

当然,您是否想要searchmatch取决于您的正则表达式。[顺便说一句,'denied_services' 不是更好的名字吗?]

于 2013-05-23T19:09:28.910 回答
1

你有一个XY 问题

以下是在迭代列表时删除列表元素的两种方法:

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()返回一个迭代器,不必创建新列表。

于 2013-05-23T19:31:41.950 回答