Home > Software engineering >  Search substring in list of dictionaries of namedtuples keyed with an event type
Search substring in list of dictionaries of namedtuples keyed with an event type

Time:12-24

I have created a list of dictionaries of named tuples, keyed with an event type.

[{'EVENT_DELETE': DeleteRequestDetails(rid=53421, user='user1', type='EVENT_DELETE', reviewed=1, approved=1, completed=0)},{'EVENT_DELETE': DeleteRequestDetails(rid=13423, user='user2', type='EVENT_DELETE', reviewed=1, approved=1, completed=0)},{'EVENT_DELETE': DeleteRequestDetails(rid=98343, user='user2', type='EVENT_DELETE', reviewed=1, approved=0, completed=0)}]

What would be the most pythonic method to return/print results that only contain "approved=1", or "reviewed=1" and "approved=0"?

CodePudding user response:

Not sure what output format you want exactly, but here's a demo for approved == 1.

>>> from collections import namedtuple
>>> DeleteRequestDetails = namedtuple('DeleteRequestDetails', 'rid user type reviewed approved completed')
>>> lst = [{'EVENT_DELETE': DeleteRequestDetails(rid=53421, user='user1', type='EVENT_DELETE', reviewed=1, approved=1, completed=0)},{'EVENT_DELETE': DeleteRequestDetails(rid=13423, user='user2', type='EVENT_DELETE', reviewed=1, approved=1, completed=0)},{'EVENT_DELETE': DeleteRequestDetails(rid=98343, user='user2', type='EVENT_DELETE', reviewed=1, approved=0, completed=0)}]
>>> [v for d in lst for v in d.values() if v.approved == 1] 
[DeleteRequestDetails(rid=53421, user='user1', type='EVENT_DELETE', reviewed=1, approved=1, completed=0),
 DeleteRequestDetails(rid=13423, user='user2', type='EVENT_DELETE', reviewed=1, approved=1, completed=0)]

CodePudding user response:

Here would be a possible solution:

# data = [{'EVENT_DELETE': DeleteRequestDetails(rid=53421, user='user1', type='EVENT_DELETE', reviewed=1, approved=1, completed=0)},{'EVENT_DELETE': DeleteRequestDetails(rid=13423, user='user2', type='EVENT_DELETE', reviewed=1, approved=1, completed=0)},{'EVENT_DELETE': DeleteRequestDetails(rid=98343, user='user2', type='EVENT_DELETE', reviewed=1, approved=0, completed=0)}]

res = filter(
    lambda _: _.approved == 1 or (_.reviewed == 1 and _.approved == 0),
    (b for a in data for b in a.values())
)
print(next(res))
# DeleteRequestDetails(rid=53421, user='user1', type='EVENT_DELETE', reviewed=1, approved=1, completed=0)

Basically, we just the builtin filter function and use a custom (lambda-) function.

Note that filter returns a generator-like object. You can wrap it in list if e.g. you need to access the data multiple times.


PS

As @PatrickArtner pointed out, having a list of dicts w/ 1 value doesn't make sense. Something like this makes more sense:

data = {
    "EVENT_DELETE": [
        DeleteRequestDetails(rid=53421, user='user1', type='EVENT_DELETE', reviewed=1, approved=1, completed=0),
        DeleteRequestDetails(rid=13423, user='user2', type='EVENT_DELETE', reviewed=1, approved=1, completed=0),
        DeleteRequestDetails(rid=98343, user='user2', type='EVENT_DELETE', reviewed=1, approved=0, completed=0)
    ]
}

This makes the solutions also much cleaner and simpler as there is no need to loop through values, e.g.

res = filter(
    lambda _: _.approved == 1 or (_.reviewed == 1 and _.approved == 0),
    data["EVENT_DELETE"]
)
  • Related