【问题标题】:Finding minimum value from a dictionary whose values are lists of objects从值是对象列表的字典中查找最小值
【发布时间】:2019-05-04 15:07:36
【问题描述】:

我有一个服务类型的 Python 对象列表。还有另一个字典grps,其中对象根据数据成员进行分组。同一组中的对象对其分组所依据的数据成员具有完全相同的值。

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)

上面有两组,一组对应features = [1],一组对应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>]})

对于每个这样的组,我想返回一个具有最小成本值的服务对象,也就是说,在上面,第一组将返回s11服务,第二组将返回s15服务,因为那是组中唯一的对象。

还有没有更好的方法可以在不使用字典的情况下做到这一点,比如只使用列表就可以做到吗?

【问题讨论】:

    标签: python dictionary


    【解决方案1】:

    在列表解析中,您可以在组的每个成员上调用min(),并使用获取cost 属性的键。 operator.attrgetter 很方便:

    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]
    

    【讨论】:

    • lambda x: x.costattrgetter('cost') 作为键 @MarkMeyer 之间是否存在权衡?
    • @DeveshKumarSingh 这是个好问题。我认为attrgetter 更容易阅读。有一些讨论 here suggesting it's faster,尽管在大多数情况下可能并不明显。
    【解决方案2】:

    现在您有了字典,使用min 及其key 参数找到成本最低的对象:

    for k, v in grps.items():
        print(min(v, key=lambda x: x.cost))
    
    # <__main__.service object at 0xeac0f090>
    # <__main__.service object at 0xeac0f110> 
    

    【讨论】:

      【解决方案3】:

      您可以在cost 属性的每个子列表上调用min(),并将这些对象附加到列表中。 min_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]
      

      一个单行列表-理解相同的将是

      min_costs = [min(v, key=lambda x:x.cost) for v in grps.values()]
      

      【讨论】:

      • 我想退回物品而不仅仅是成本
      • 已更新@kauray 请检查!
      猜你喜欢
      • 1970-01-01
      • 2015-08-05
      • 2013-11-06
      • 1970-01-01
      • 2015-01-16
      • 1970-01-01
      • 1970-01-01
      • 2016-05-22
      • 2020-07-26
      相关资源
      最近更新 更多