通过正则表达式匹配过滤字典列表

时间:2013-05-23 18:58:25

标签: python python-2.7 list-comprehension

我正在编写一个收集指标的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在他的回答中所说的那样处理这个问题。

2 个答案:

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