Reputation: 467
names = ['vapp1', 'vapp3', 'vapp4', 'vapp2']
vapps = [{'name':'vapp2', 'ip': '11.21.18.24', 'obj': 'obj523'}, {'name':'vapp3', 'ip': '11.21.18.27', 'obj': 'obj234'}, {'name':'vapp5', 'ip': '11.21.18.25', 'obj': 'obj246'}]
result = [vapp for vapp in vapps if vapp['name'] in names]
print result
Using this list/dict comprehension I am getting what I want in result. But I also want to print that vapp1
& vapp4
are not there in vapps
.
What is the most efficient way ? or How to avoid extra looping to achieve all of this so that I will get a filtered list of dictionary whose names are common in the list names
. And also I can print those names which are not there.
Upvotes: 0
Views: 954
Reputation: 153
You could do following
just using some set properties we can get it
vapps_names = [vapp['name'] for vapp in vapps]
now Values not in vapps but in names
not_in_vapps = set(names) - set(vapps_names)
{'vapp1', 'vapp4'}
Values in names not in vapps
not_in_names = set(vapps_names) - set(names)
{'vapp5'}
Upvotes: 1
Reputation: 12178
You could abuse the short-circuiting of and
like so:
>>> result = [vapp for vapp in vapps if
... vapp['name'] in names and
... (names.remove(vapp['name']) or 1)]
>>> names # now contains names not found in vapps
['vapp1', 'vapp4']
This will yield the same result list as before, and modifies names
so it removes found vapp names as a side effect.
This works because the and
clause is only evaluated when the first part of the statement (vapp['name'] in names
) is True
. The or 1
part is needed because .remove()
yields None
, which is False
in a boolean context.
List comprehensions with side effects are generally discouraged as bad style, though - and your names
list will get modified, so better save a copy if you need it again.
Generally, do not worry about performance, and just use two loops - or write it out in a readable, classic loop.
Upvotes: 1