我有一个菜单字典项目作为关键,价格作为价值。可能存在比单个项目便宜一点的项目组合。对于exa:
menu = {
('burger',) : 5.00,
('pizza',) : 12.00,
('coke',) : 4.00,
('macpuff',) : 4.00,
('pasta',) : 3.00,
('french_fries',) : 2.00,
('burger', 'coke', 'french_fries') : 10.00,
('pizza', 'coke') : 15.00,
}
现在假设我订购的物品很少,那么输出将是给定订单的最小数量:
I/P > burger, coke
O/P > 9 (5.00 + 4.00)
I/P > burger, coke, french_fries
O/P > 10.00
I/P > pizza, coke, french_fries
O/P > 17.00 (15.00 + 2.00)
这是我为所有价格尝试的代码,我将用作生成器:
def isSubset(a, b):
"""
compare two iterable and return true if first is subset of second
"""
b = list(b)
if not hasattr(a, '__iter__'):
a = [a]
for each in a:
try:
b.remove(each)
except ValueError:
return False
return True
def rest_min_price(order):
if order:
for item, price in menu.iteritems():
if isSubset(order[0], item):
new_order = order[1:]
for itm in item:
try:
new_order.remove(itm)
except ValueError:
pass
yield price + rest_min_price(new_order)
但是当我运行它时,它会说类型错误:
for each in rest_min_price(order_item):
print each
TypeError: unsupported operand type(s) for +: 'int' and 'generator'
答案 0 :(得分:5)
谢谢大家的回复。在某个地方,我使用了你的建议,现在我用不同的实现方法解决了它。
这是我的代码:
class Rest_Menu():
def __init__(self, menu):
self.menu = menu
self.all_price = []
def min_price(self, order, total_price=0):
"""
Return minm menu price by calculating all possible combination.
"""
if order:
for item, price in self.menu.iteritems():
if isSubset(order[0], item):
new_order = [each for each in order]
for itm in item:
try:
new_order.remove(itm)
except ValueError:
pass
self.min_price(new_order, price+total_price)
else:
self.all_price.append(total_price)
return min(self.all_price)
再次感谢。 :)
答案 1 :(得分:2)
你误解了yield
。包含yield
的函数神奇地成为生成器。如果你只是调用它,你会得到一个你不能直接使用的生成器对象;你需要调用它的next()
方法来从中抽取值。大多数情况下,您将其放入for
循环。
>>> def genDemo(n):
... while n > 0:
... yield n
... n -= 1
...
>>>
>>> gd = genDemo(3)
>>> gd
<generator object genDemo at 0x7fce12152820>
>>> gd.next()
3
>>> gd.next()
2
>>> gd.next()
1
>>> gd.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> for x in genDemo(3):
... print x
...
3
2
1
>>> _
您的代码只是一个正常的递归函数;它可以使用return
。
当你不想在内存中获得整个序列时,生成器很方便;它具有非常长且无限的序列,因此最有意义。您可以生成排列,直到找到所需的排列,或生成随机数,直到找到所需的数字,或者从套接字读取,直到您收到退出消息等。
关于子集:除非您的数据以相同的方式排序,否则无法懒惰地检查子集。使用您拥有的数据集,您最好使用内置的set
。
答案 2 :(得分:0)
您的问题在于尝试将生成器与递归结合起来:
yield price + rest_min_price(new_order)
此处price
是int
,但rest_min_price()
是generator
(因为您yield
,而不是return
,其结果)因此,您无法将它们添加到一起并获得TypeError
。
您需要遍历生成器中的项目:
for item in rest_min_price(order_item):
# process the item
# yield result with price