Объединение объектов на основе определенных атрибутов и объединение (суммирование) определенных других атрибутов - PullRequest
0 голосов
/ 27 сентября 2018

Допустим, у меня есть MyObject с атрибутами attr_a, attr_b и attr_c и quantity.

Я хотел бы объединить их количества, если они имеют одинаковые attr_a,attr_b и attr_c

Вот пример и мой подход.Есть лучший способ сделать это?Например;что если я хотел сохранить порядок своих списков после их объединения?

class MyObject:
    def __init__(self, attr_a, attr_b, attr_c, quantity):
        self.attr_a = attr_a
        self.attr_b = attr_b
        self.attr_c = attr_c
        self.quantity = quantity

    def __eq__(self, rhs):
        if type(rhs) is type(self):
            return self.attr_a == rhs.attr_a and self.attr_b == rhs.attr_b and self.attr_c == rhs.attr_c
        else:
            return False

    def __hash__(self):
        return hash((self.attr_a, self.attr_b, self.attr_c))

    def __repr__(self):
        return "<{}, {}, {}, {}>".format(self.attr_a, self.attr_b, self.attr_c, self.quantity)


from collections import defaultdict

pos1 = [MyObject("AAA", "BBB", "A123", 1000), MyObject("AAA", "CCC", "A123", 2000)]
pos2 = [MyObject("AAA", "BBB", "A123", 2000), MyObject("AAA", "CCC", "A123", -2000), MyObject("AAA", "DDD", "A999", 200)]

merge = defaultdict(int)

for p in pos1 + pos2:
    merge[p] += p.quantity

res = []
for k, v in merge.items():
    k.quantity = v
    res.append(k)

print(res)

"""
Expected output: [<AAA, BBB, A123, 3000>, <AAA, CCC, A123, 0>, <AAA, DDD, A999, 200>]
"""

1 Ответ

0 голосов
/ 27 сентября 2018

Ну, я думаю, что не стоит «подгонять» функции __eq__ и т. Д. Для конкретного случая использования: сейчас это означает, что MyObject("AAA", "BBB", "A123", 1000) считается равным MyObject("AAA", "BBB", "A123", 1425).Для сценария «слияния» таких объектов вместе это может сработать, но это подразумевает, что другие (простые) сценарии использования могут привести к большому количеству дополнительной логики.* количество существующих MyObject в целом: вы не знаете, какие переменные указывают на этот объект.В результате это может означать, что список, содержащий MyObject s, внезапно имеет список, в котором quantities отличается.

Возможно, было бы лучше реализовать такую ​​функцию, как get_key:

class MyObject:
    def __init__(self, attr_a, attr_b, attr_c, quantity):
        self.attr_a = attr_a
        self.attr_b = attr_b
        self.attr_c = attr_c
        self.quantity = quantity

    <b>def get_key(self):
        return (self.attr_a, self.attr_b, self.attr_c)</b>

    def __repr__(self):
        return "<{}, {}, {}, {}>".format(self.attr_a, self.attr_b, self.attr_c, self.quantity)

Затем мы выполняем более или менее похожий алгоритм, но создаем новые MyObject s:

from collections import defaultdict
res = defaultdict(int)

for obj in objs:
    res[obj.get_key()] += obj.quantity

result = [MyObject(*k, v) for k, v in res.items()]

Создание некоторой функции clone для копирования MyObject вместес новым количеством может также улучшить дизайн кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...