【问题标题】:How to check for duplicate attributes in object list and merge them如何检查对象列表中的重复属性并合并它们
【发布时间】:2018-02-06 14:50:57
【问题描述】:

我有一个具有qtconsconsper 属性的对象列表,并且必须合并所有具有相同consper 值的对象。最好的方法是什么?该列表已按consper 排序。

示例: 带有house类的对象列表:

class house():
    def __init__(self, qt, cons, consper):
        self.qt = qt
        self.cons = cons
        self.consper = consper

打开这个列表:

l = [
house(2, 20, 10),
house(3, 31, 10),
house(6, 70, 11),
house(2, 40, 20),
house(1, 25, 25)]

进入这个列表:

l_new = [
house(5, 51, 10),
house(6, 70, 11),
house(2, 40, 20),
house(1, 25, 25)]

通过添加前两个对象(因为它们的属性 consper 是等价的)

【问题讨论】:

  • (......两个高代表用户重新回答问题......)

标签: python python-3.x list object data-structures


【解决方案1】:

如果项目已经按该属性排序,您可以使用itertools.groupby 获取组,使用sum 获取其他属性的总和。您还必须先将组转换为 list,因为它们是迭代器。

>>> from itertools import groupby
>>> house.__repr__ = lambda h: "house(%r, %r, %r)" % (h.qt, h.cons, h.consper)
>>> [house(sum(h.qt for h in g), sum(h.cons for h in g), k) 
...  for k, g in ((k, list(g)) for k, g in groupby(l, key=lambda h: h.consper))]
[house(5, 51, 10), house(6, 70, 11), house(2, 40, 20), house(1, 25, 25)]

或者使用字典:

>>> d = {}
>>> for h in l:
...     qt, cons = d.get(h.consper, (0, 0))
...     d[h.consper] = qt + h.qt, cons + h.cons
...
>>> [house(a, b, c) for a, (b, c) in d.items()]
[house(25, 1, 25), house(10, 5, 51), house(11, 6, 70), house(20, 2, 40)]

【讨论】:

    【解决方案2】:

    不使用 itertools,你可以这样做:

    class House():
            def __init__(self, qt, cons, consper):
                self.qt = qt
                self.cons = cons
                self.consper = consper
    
            def __str__(self):
                return "House(" + str(self.qt) + "," + str(self.cons) + "," + str(self.consper) + ")"
    
            def __repr__(self):
                return self.__str__()
    
    def merge_dups(house_list):
        res = []
        house_map = {}
        for h in house_list:
            if h.consper in house_map:
                other_house = house_map[h.consper]
                merged_house = House(h.qt + other_house.qt,
                                     h.cons + other_house.cons,
                                     h.consper)
                res.remove(other_house)
                res.append(merged_house)
    
            else:
                house_map[h.consper] = h
                res.append(h)
        return res
    
    print(merge_dups([
    House(2, 20, 10),
    House(3, 31, 10),
    House(6, 70, 11),
    House(2, 40, 20),
    House(1, 25, 25)]))
    

    输出

    [House(5,51,10), House(6,70,11), House(2,40,20), House(1,25,25)]
    

    【讨论】:

      【解决方案3】:

      你可以使用itertools.groupby:

      import itertools
      class house():
        def __init__(self, qt, cons, consper):
          self.qt = qt
          self.cons = cons
          self.consper = consper
        def __repr__(self):
          return self.__class__.__name__+"({qt}, {cons}, {consper})".format(**self.__dict__)
      
      l = [house(2, 20, 10),
       house(3, 31, 10),
       house(6, 70, 11),
       house(2, 40, 20),
       house(1, 25, 25)]
      new_l = [(a, [(i.qt, i.cons) for i in list(b)]) for a, b in itertools.groupby(sorted(l, key=lambda x:x.consper), key=lambda x:x.consper)]
      final_data = [house(*[sum(i) for i in zip(*b)]+[a]) for a, b in new_l]
      

      输出:

      [house(5, 51, 10), house(6, 70, 11), house(2, 40, 20), house(1, 25, 25)]
      

      【讨论】:

        【解决方案4】:

        一个简单的解决方案是使用字典,如下所示:

        l = [
        house(2, 20, 10),
        house(3, 31, 10),
        house(6, 70, 11),
        house(2, 40, 20),
        house(1, 25, 25)]
        dic= {}
        for x in l :
            temp = dic.get(x.consper,house(0,0,0))
            x.qt += temp.qt
            x.cons += temp.cons
            dic[x.consper]=x
        
        print('####################')
        for x in dic.keys():
            print(x)
        

        【讨论】:

        • 这不会添加,只会消除匹配项。
        • 是的,我的错,我已经更新了,谢谢@tobias_k
        猜你喜欢
        • 2019-03-17
        • 2023-03-08
        • 1970-01-01
        • 2021-01-10
        • 1970-01-01
        • 1970-01-01
        • 2014-12-27
        • 2021-12-11
        • 1970-01-01
        相关资源
        最近更新 更多