5

私はキーとしてメニューディクテーションアイテムを、値として価格を持っています。単品よりも少し安くなる商品の組み合わせもあるかもしれません。エクサの場合:

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'
4

3 に答える 3

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)

再度、感謝します。:)

于 2014-01-03T05:36:42.650 に答える
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

于 2014-01-02T10:24:41.430 に答える
0

あなたの問題は、ジェネレーターを再帰と組み合わせようとするときに発生します。

yield price + rest_min_price(new_order)

ここにpriceがありますが、です (その結果ではなく、あなたのため) 。intrest_min_price()generatoryieldreturnTypeError

ジェネレーターの項目をループする必要があります。

for item in rest_min_price(order_item):
    # process the item
    # yield result with price
于 2014-01-02T10:21:29.387 に答える