如何检查对象列表中的重复属性并合并它们

2024-10-01 00:26:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个属性为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是等价的)


Tags: 对象self示例列表new属性排序init
3条回答

不使用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)]

您可以使用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)]

如果项目已按该属性排序,则可以使用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)]

相关问题 更多 >