как сортировать словарь внутри списка и манипулировать данными?

Я работаю над чем-то вроде управления запасами, я застрял в сортировке и добавлении дубликатов по некоторым условиям. Мой код приведен ниже, и он отлично работает до тех пор, пока данные не находятся в списке "print (c.data_dict)"

import datetime
from itertools import groupby
from operator import itemgetter

class Supplier:
    def __init__(self, name, address, email, contact_no):
        self.name = name
        self.address = address
        self.email = email
        self.contact_no = contact_no

class Product:
   def __init__(self, name):
        self.name = name

class Company(Supplier, Product):
    data_dict = []
    def purchase(self, supplier_obj, product_obj, qty, date):
    self.data_dict.append({'supplier': supplier_obj.name, 'product': product_obj.name, 'qty': qty, 'date': date})
    return self.data_dict

s1 = Supplier('Amazon', 'kalawad road', '[email protected]', '987686')
s2 = Supplier('Flipkart', 'university road', '[email protected]', '657457')
s3 = Supplier('Alibaba', 'china town road', '[email protected]', '365213')

p1 = Product('Laptop')
p2 = Product('printer')
p3 = Product('computer')

c = Company(None, None, None, None)
c.purchase(s1, p1, 10, '2019-10-10')
c.purchase(s1, p1, 10, '2019-10-10')
c.purchase(s1, p2, 20, '2018-11-11')
c.purchase(s1, p2, 30, '2018-12-12')
c.purchase(s1, p3, 40, '2016-10-10')
c.purchase(s2, p3, 10, '2019-11-11')
c.purchase(s2, p3, 11, '2019-11-11')
c.purchase(s3, p1, 6, '2019-03-04')
c.purchase(s3, p3, 9, '2019-02-02')
print(c.data_dict)

я получаю список, содержащий как

[{'supplier': 'Amazon', 'product': 'Laptop', 'qty': 10, 'date': '2019-10-10'}, 
 {'supplier': 'Amazon', 'product': 'Laptop', 'qty': 10, 'date': '2019-10- 10'}, 
{'supplier': 'Amazon', 'product': 'printer', 'qty': 20, 'date': '2018-11-11'},
 {'supplier': 'Amazon', 'product': 'printer', 'qty': 30, 'date': '2018-12-12'},
 {'supplier': 'Amazon', 'product': 'computer', 'qty': 40, 'date':'2016-10-10'},
 {'supplier': 'Flipkart', 'product': 'computer', 'qty': 10,'date': '2019-11-11'},
 {'supplier': 'Flipkart', 'product': 'computer', 'qty': 11, 'date': '2019-11-11'},     
{'supplier': 'Alibaba', 'product': 'Laptop', 'qty': 6, 'date': '2019-03-04'}, 
{'supplier': 'Alibaba', 'product':'computer', 'qty': 9, 'date': '2019-02-02'}]

где Amazon, FLipkart & allibaba — это название поставщика, Laptop-Printer-Computer — название продукта, а qty — это количество и дата.

Я пытаюсь отсортировать приведенный выше список таким образом, чтобы, если есть та же дата от одного и того же поставщика, необходимо добавить количество. например. в Amazon - количество принтеров должно быть 50, как показано в выводе. Как мне это сделать? Я пытался сделать это с помощью itertool и модуля оператора, но не получил правильного вывода.

Мой ожидаемый результат

sample output

 Amazon
 01-01-2019      laptop       10
 02-02-1019      laptop       10
 03-03-2019      printer      50
 03-03-2019      computer     40

 Flipkart
 01-01-2019      computer      10
 31-01-2019      computer      11

 Alibaba
 2019-03-04      laptop        6
 2019-02-02      computer      6

person edward    schedule 28.03.2019    source источник


Ответы (4)


Используйте счетчик, чтобы сделать тяжелую работу.

>>> from collections import Counter
>>> counter = Counter()
>>> for d in c.data_dict:
        counter[d['supplier'],d['product'],d['date']] += d['qty']

Это дает итоги по поставщику, продукту и дате:

>>> counter
Counter({('Amazon', 'computer', '2016-10-10'): 40, ('Amazon', 'printer', '2018-12-12'): 30, ('Flipkart', 'computer', '2019-11-11'): 21, ('Amazon', 'printer', '2018-11-11'): 20, ('Amazon', 'Laptop', '2019-10-10'): 10, ('Amazon', 'Laptop', '2019-10- 10'): 10, ('Alibaba', 'computer', '2019-02-02'): 9, ('Alibaba', 'Laptop', '2019-03-04'): 6})

Чтобы распечатать его, отсортировав по поставщику, продукту и дате, вы можете сделать это. Ваш образец вывода не согласуется с датами в образце ввода в вопросе, поэтому результаты не совпадают.

>>> for (supplier, product, date), qty in sorted(counter.items()):
        print(supplier, product, date, qty)

('Alibaba', 'Laptop', '2019-03-04', 6)
('Alibaba', 'computer', '2019-02-02', 9)
('Amazon', 'Laptop', '2019-10- 10', 10)
('Amazon', 'Laptop', '2019-10-10', 10)
('Amazon', 'computer', '2016-10-10', 40)
('Amazon', 'printer', '2018-11-11', 20)
('Amazon', 'printer', '2018-12-12', 30)
('Flipkart', 'computer', '2019-11-11', 21)

Добавьте вызов format() в вызов print(), чтобы сделать его красивым.

person BoarGules    schedule 28.03.2019

Я думаю, проблема здесь в том, что вы на самом деле не пытаетесь сортировать, вы пытаетесь преобразовать данные

Если я правильно понимаю, когда компания покупает продукт, который она уже купила у того же поставщика в тот же день, мы должны добавить количество.

Один простой способ сделать это — добавить эту логику в функцию покупки.

def purchase(self, supplier_obj, product_obj, qty, date):
    for purchase in self.data_dict:
        if purchase['supplier'] == supplier_obj.name and purchase['product'] == product_obj.name and purchase['date'] == date:
            purchase['qty']+=qty
            return self.data_dict
    self.data_dict.append({'supplier': supplier_obj.name, 'product': product_obj.name, 'qty': qty, 'date': date})
    return self.data_dict

Более эффективным способом сделать это было бы хранить данные в большом словаре, и только при вызове print вы форматируете их так, как хотите. Приведенный выше код должен правильно отформатировать ваш список.

person Nick Koul    schedule 28.03.2019

Вот как вы можете удалить дубликаты и суммировать одни и те же продукты, которые были добавлены в тот же день и той же компанией.

new_data = []
for entry in data:
    if entry not in new_data:
        for i in new_data:
            if all([entry['product'] == i['product'],
                    entry['supplier'] == i['supplier'],
                    entry['date'] == i['date']]):
                i['qty'] += entry['qty']
                break
        new_data.append(entry)

print(*new_data, sep='\n')

Вывод:

{'date': '2019-10-10', 'product': 'Laptop', 'supplier': 'Amazon', 'qty': 10}
{'date': '2018-11-11', 'product': 'printer', 'supplier': 'Amazon', 'qty': 20}
{'date': '2018-12-12', 'product': 'printer', 'supplier': 'Amazon', 'qty': 30}
{'date': '2016-10-10', 'product': 'computer', 'supplier': 'Amazon', 'qty': 40}
{'date': '2019-11-11', 'product': 'computer', 'supplier': 'Flipkart', 'qty': 21}
{'date': '2019-11-11', 'product': 'computer', 'supplier': 'Flipkart', 'qty': 11}
{'date': '2019-03-04', 'product': 'Laptop', 'supplier': 'Alibaba', 'qty': 6}
{'date': '2019-02-02', 'product': 'computer', 'supplier': 'Alibaba', 'qty': 9}
person Filip Młynarski    schedule 28.03.2019

Я немного повеселился, поэкспериментировав с тем, как легко модифицировать данные. Это не самый красивый способ, пожалуйста, обратитесь к ответу Филипа, если вы хотите что-то эффективное, не сильно меняя код.

import datetime
import attr

Supplier= attr.make_class('Supplier',['name', 'address', 'email', 'contact_no', 'purchase_per_date_per_product'])

Product = attr.make_class('Product',['name'])

Purchase = attr.make_class('Purchase',['supplier', 'product','qty','date'])

class Company():
    data_dict = {}
    def add_purchase(self, supplier_obj, product_obj, qty, date):
        if [product_obj,date] in supplier_obj.purchase_per_date_per_product:
            self.data_dict[supplier_obj.name][date][product_obj.name]+= qty
        else:
            if supplier_obj.name not in self.data_dict:
                self.data_dict[supplier_obj.name]={}
            supplier_obj.purchase_per_date_per_product += [[product_obj,date]]
            self.data_dict[supplier_obj.name][date]={product_obj.name:qty}
        return self.data_dict
person Born Tbe Wasted    schedule 28.03.2019