Reputation: 719
I have a list of Python Objects of type class Service. There is another dictionary grps
where the objects are grouped according to a data member. Objects in the same group have exactly the same value for the data member according to which it is grouped.
from collections import defaultdict
class service:
def __init__(self, tasknum, candidatenum, features, cost):
self.tasknum = tasknum
self.candidatenum = candidatenum
self.features = features
self.cost = cost
s11 = service(1,1, features = [1], cost = 30)
s12 = service(1,2, features = [1], cost = 50)
s13 = service(1,3, features = [1], cost = 70)
s14 = service(1,4, features = [1], cost = 200)
s15 = service(1,5, features = [2], cost = 20)
lst = []
lst.append(s11)
lst.append(s12)
lst.append(s13)
lst.append(s14)
lst.append(s15)
grps = defaultdict(list)
for x in lst:
grps[tuple(x.features)].append(x)
In the above, there are two groups, one corresponding to features = [1]
, and one corresponding to features = [2]
.
defaultdict(<class 'list'>, {(1,): [<__main__.service object at 0x7efe19a2d6d8>, <__main__.service object at 0x7efe19a2d4e0>, <__main__.service object at 0x7efe1d7e9550>, <__main__.service object at 0x7efe1d7e9588>], (2,): [<__main__.service object at 0x7efe1d7e95c0>]})
For each such group, I would like to return a service object having the minimum cost value, that is, in the above, the first group would return s11
service and the second group would return s15
service since that is the only object in the group.
And is there any better way to do this without using the dictionary, like can this be done by just using lists?
Upvotes: 1
Views: 644
Reputation: 92450
In a list comprehension you can call min()
on each member of the groups and use a key that gets the cost
attribute. operator.attrgetter
handy for this:
from operator import attrgetter
# array of min-cost services
mins = [min(g, key = attrgetter('cost')) for g in grps.values()]
# just the costs
[c.cost for c in mins] # [30, 20]
Upvotes: 4
Reputation: 20500
You can just call min()
on each sublist on the cost
attribute, and append those objects to a list. min_costs
will be the objects with mimimum costs.
#List to hold all objects with min costs
min_costs = []
for k, v in grps.items():
# Calculate minimum for all sublists on cost attribute
min_costs.append(min(v, key=lambda x:x.cost))
#Print the costs of objects with min costs
print([c.cost for c in min_costs])
#[30, 20]
A one liner list-comprehension for the same will be
min_costs = [min(v, key=lambda x:x.cost) for v in grps.values()]
Upvotes: 1
Reputation: 26039
Now that you have a dictionary, find the object having minimum cost with min
and its key
argument:
for k, v in grps.items():
print(min(v, key=lambda x: x.cost))
# <__main__.service object at 0xeac0f090>
# <__main__.service object at 0xeac0f110>
Upvotes: 1