сортировать, добавлять и удалять аналогичные индексы списка словарей, используя FIFO - PullRequest
0 голосов
/ 17 апреля 2019

Я пытаюсь решить эту проблему, и у меня есть список словаря, похожий на этот. (Это словарь из «метода покупки»)

[{'qty': 20, 'price': 2000.0, 'product': 'Computer', 'date': '2017-03-05'}, 
{'qty': 22, 'price': 5000.0, 'product': 'Computer', 'date': '2017-11-11'},
{'qty': 6, 'price': 1523.0, 'product': 'Computer', 'date': '2018-02-03'},
{'qty': 10, 'price': 1000.0, 'product': 'Computer', 'date': '2018-12-05'},
{'qty': 20, 'price': 2000.0, 'product': 'Computer', 'date': '2019-11-06'},
{'qty': 10, 'price': 1000.0, 'product': 'Computer', 'date': '2019-08-02'}
]

Я пытаюсь создать метод с именем def sale(quantity, date):. В этой функции я хочу передать количество и дату, если достаточное количество товара доступно до даты продажи, это позволяет мне продать это количество.

например. если я передам количество = 30 и дату = 2018-01-01, это должно позволить мне продать, потому что это возможно для продажи из-за достаточного количества, и после этого оставшееся количество и цена должны быть рассчитаны согласно и должны быть добавлены к выше список словаря.

например. в нашем случае

{'qty': 12, 'price': 2000.0, 'product': 'Computer', 'date': '2018-01-01'}

и первые 2 словаря следует удалить, потому что мы их уже продали! (это как инвентарь FIFO)

Вот мой код, который я пытаюсь сделать это. Однако я получаю ошибки и не получаю желаемый результат. Любые другие возможности? Как мне заставить это работать?

import datetime
from collections import Counter

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

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

class Company(Supplier, Product):
    data_dict = []
    def purchase(self, product_obj, qty, price, date=datetime.date.today()):
    self.data_dict.append({'product': product_obj.name, 'qty': qty, 'price': price, 'date': str(date)})

    def sale(self, sell_qty, sell_date=datetime.date.today()):
        a = 0
        p = 0
        unit_val = 0
        new_price = 0
        newdict = (sorted(self.data_dict, key=lambda x: x['date']))

        for dt in newdict:
            a += dt['qty']
            p += dt['price']
            if sell_date > dt['date']:
                if sell_qty <= a:
                   unit_val = float(p / a)
                    new_price = unit_val * a
                    a -= sell_qty
                    self.data_dict.append({'product': product_obj.name, 'qty': a, 'price': new_price, 'date': str(sell_date)})
                    print("sold!")

            else:
                print("Sorry, not enough qty.\n")


C = Company()
PRODUCT_OBJ = Product()
PRODUCT_OBJ.add_product('Computer')

while True:

    option = int(input(" 1. You want to add stock of the product!\n2. Want to sell product?\n"))

    if option == 1:
        qty = int(input("Enter the qty of the product.\n"))
        price = float(input("Enter the price of the product.\n"))
        purchase_date = input("Enter purchase date.\n")
        C.purchase(PRODUCT_OBJ, qty, price, purchase_date)

    elif option == 2:
        qty = int(input("Enter the qty you wanna sell, pal!"))
        sale_date = input("Enter sell date.\n")
        C.sale(qty)

получение ошибок:

Traceback (most recent call last):
  File "G:/python/test.py", line 63, in <module>  C.sale(qty)
  File "G:/python/test.py", line 33, in sale if sell_date > dt['date']:
 TypeError: '>' not supported between instances of 'datetime.date' and 'str'

желаемый вывод:

[{'qty': 12, 'price': 2000.0, 'product': 'Computer', 'date': '2018-01-01'},
{'qty': 6, 'price': 1523.0, 'product': 'Computer', 'date': '2018-02-03'},
{'qty': 10, 'price': 1000.0, 'product': 'Computer', 'date': '2018-12-05'},
{'qty': 20, 'price': 2000.0, 'product': 'Computer', 'date': '2019-11-06'},
{'qty': 10, 'price': 1000.0, 'product': 'Computer', 'date': '2019-08-02'}
]

Ответы [ 2 ]

1 голос
/ 17 апреля 2019

@ adrtam показал вам, как исправить ошибку, которую вы опубликовали. Но у вашего кода есть серьезные проблемы. Я не буду все исправлять, но вот несколько советов:

  • класс Supplier: add_supplier должно быть __init__. Вы создаете нового поставщика с: s = Supplier("foo", "bar", "baz@baz", "no")
  • класс Product: то же самое
  • класс Company:
    • не должно наследоваться от Product и Supplier (компания является продуктом и поставщиком? Нет)
    • пропускает метод __init__: data_dict в настоящее время является полем класса, должно быть полем экземпляра
  • избегайте имен, таких как a, p: всегда используйте значимые имена.
  • в желаемом выводе, нет причин устанавливать после продажи дату первой строки на «2018-01-01»
  • предпочитают глаголы называть ваш метод (зависит от контекста): sell вместо sale.

Теперь давайте посмотрим на метод sell. Я предполагаю, что это акции FIFO: вы сначала продаете товары, которые были куплены первыми. Вот простая идея:

  • Перебирать строки и суммировать имеющееся количество.
  • Как только количество станет достаточным, выход из цикла
  • Затем удалите просматриваемые строки и исправьте количество последней просматриваемой строки.

Пример кода (я предполагаю, что данные всегда упорядочены по дате: для обеспечения этого вы можете использовать приоритетную очередь ):

data = [{'qty': 20, 'price': 2000.0, 'product': 'Computer', 'date': '2017-03-05'},
    {'qty': 22, 'price': 5000.0, 'product': 'Computer', 'date': '2017-11-11'},
    {'qty': 6, 'price': 1523.0, 'product': 'Computer', 'date': '2018-02-03'},
    {'qty': 10, 'price': 1000.0, 'product': 'Computer', 'date': '2018-12-05'},
    {'qty': 20, 'price': 2000.0, 'product': 'Computer', 'date': '2019-11-06'},
    {'qty': 10, 'price': 1000.0, 'product': 'Computer', 'date': '2019-08-02'}]

wanted = {'qty': 30, 'date': '2018-01-01'}

def sell(wanted):
    global data # NEVER do this: just for the example
    assert wanted['qty'] > 0
    qty = 0
    for i, row in enumerate(data):
        # too late!
        if row['date'] > wanted['date']:
            raise Exception("Sorry, not enough qty. Operation cancelled")

        qty += row['qty']
        # we have enough Computers!
        if qty >= wanted['qty']:
            break
    else: # loop completes normally
        raise Exception("Sorry, not enough qty. Operation cancelled")

    remaining_qty_in_last_row = qty-wanted['qty']
    # copy of the last row with a new quantity + the remaining rows
    data = [{**row, 'qty':remaining_qty_in_last_row}] + data[i+1:]
    print ("Sold!")

for wanted in [{'qty': 30, 'date': '2018-01-01'}, {'qty': 30, 'date': '2018-01-01'}]:
    try:
         sell(wanted)
    except e:
         print(e)
    print ("data", data)

Это всего лишь набросок алгоритма: вам нужно потренироваться, чтобы извлечь правильный дизайн классов и методов.

0 голосов
/ 17 апреля 2019

Давайте просто исправим ошибку, которую вы опубликовали:

Traceback (most recent call last):
  File "G:/python/test.py", line 63, in <module>  C.sale(qty)
  File "G:/python/test.py", line 33, in sale if sell_date > dt['date']:
 TypeError: '>' not supported between instances of 'datetime.date' and 'str'

Проблема в том, что у вас есть sell_date в объекте datetime, но ваша дата в словаре является строкой.Вам нужно преобразовать их в один и тот же тип, чтобы сравнение работало.Два способа сделать это:

  1. Сделать ваш объект даты-времени строкой фиксированного формата, которую можно сравнивать:

    if sell_date.strftime("%Y-%m-%d") > dt['date']:
    
  2. Анализ датыстрока в объекте datetime:

    import datetime
    if sell_date > datetime.datetime.strptime(dt['date'], '%Y-%m-%d'):
    
...