Reputation: 2269
I'm writing a python script which collects metrics and I have:
collected
, a list containing all messages, stored as dictionariesdenied_metrics
, a list containing all compiled regular expressionsI want to be able to inhibit the forwarding of those messages in which collected[i]['service']
matches at least one regular expression in denied_metrics
.
I was trying to achieve my goal using list comprehension and filter
, but I didn't manage to do that way.
Given that messages have the following structure:
msg = {
'service': 'foo',
'metric': 1.0,
'denied': False
}
actually I'm filtering all collected
messages like follows
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 ]
Is there a (better?) way to obtain a list of allowed messages using just a combination of list comprehension and filter
or reduce
?
I was not aware about the possibility to approach the problem like @eyquem suggested by in his answer.
Upvotes: 0
Views: 1780
Reputation: 353059
IIUC, I might do do something like
allowed = [msg for msg in collected
if not any( dm.search(msg['service'])
for dm in denied_metrics) ]
For example:
>>> 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}]
Whether you want search
or match
depends upon your regexes, of course. [BTW, wouldn't 'denied_services' be a better name?]
Upvotes: 2
Reputation: 27575
You have an XY problem.
Here are two ways to delete elments of a list while iterating in it:
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]
In the last code reversed()
returns an iterator, no new list has to be created.
Upvotes: 1