2016-12-28 4 views
1

私は、単位当たりの価格と単位数に基づいて私の株式の合計額を計算しなければなりません。このコードを(パラダイムのように)機能的なプログラムに変換するにはどうすればよいですか?

prices = { 
    "banana" : 4, 
    "apple" : 2, 
    "orange" : 1.5, 
    "pear" : 3, 
} 
stock = { 
    "banana" : 6, 
    "apple" : 0, 
    "orange" : 32, 
    "pear" : 15, 
} 

for key in prices: 
    print key 
    print "price: %s" % prices[key] 
    print "stock: %s" % stock[key] 

total = 0 
for key in prices: 
    total = total + prices[key]*stock[key] 
print total 

そして、私はこれで最後のブロックを交換することにより、より機能的なプログラムに変換しようとしました:私は、Pythonで、次のコードを持っている

def total(x): 
    if len(x) == 1: 
     return prices[prices.keys()[0]]*stock[prices.keys()[0]] 
    else: 
     return prices[prices.keys()[0]]*stock[prices.keys()[0]] + total(x[1:]) 

print total(prices) 

上記のコードはこのエラーを取得します。

Traceback (most recent call last): 
    File "python", line 30, in <module> 
    File "python", line 28, in total 
TypeError: unhashable type 

私のコードをより機能的なプログラミングバージョンに修正してもらえますか?

答えて

1

まずは、不可欠ループを見てみましょう:

total = 0 
for key in prices: 
    total = total + prices[key]*stock[key] 
print total 

が不可欠ループを調べると、すべての反復を変更されている2つの事がprices.keys()から発信され、それ自体で結構です、とkeyれ、totalです。だから、それらから何かが必要になるでしょう。

自然言語で命令語ループを書き直してみましょう。私は英語を選ぶでしょう。 keyprices [またはおそらくprices.keys()にする]の場合は、合計をprices[key]*stock[key]増加してください。 、prices.keys()に各keyについて

prices[key]*stock[key]で実行中の合計を増やす:我々は、全変異することはできませんので

、の文を書き換えてみましょう。

そして、prices.keys()は、果物の名前なので、のは再びそれを書いてみましょう:fruitNamesの各keyに対して

prices[key]*stock[key]で実行中の合計を増加させます。

ここで、私はかなり説明できない精神的なジャンプです。ループの繰り返しごとにtotalkeyが変化しているというヒントがありました。今はtotalを無視することができます(私はtail-recursion-optimizationとこれをさらに混同しないためです)。機能的なスタイルの場合、keyはキーの全体のリストfruitNamesになります。

def totalRecur(fruitNames): 

ここで、基本ケースについて考えてみましょう。 prices(およびstock)が空の場合はどうなりますか?さて、合計は0になります。

if len(fruitNames) == 0: 
     return 0 

これはうまく見えます。今、ゼロの位置にアイテムが1つしかない場合はどうなりますか?

key = fruitNames[0] 
    return prices[key] * stock[key] 

我々はtotalRecur([]) == 0は、我々は代わりにリスト項目を1つだけ持っているので、我々はfruitNames[1:]が空リストであることを知って、

return prices[key] * stock[key] + totalRecur([]) 

を言うことができていることを知っているので:

return prices[key] * stock[key] + totalRecur(fruitNames[1:]) 

totalRecurの良好な定義を書くのに十分な情報が必要です。

+1

再帰は一般的にPythonでは避けなければなりません。機能!=再帰。 –

+0

ああ、右、 'StackOverflowError'は吸う。 – LexieHankins

+1

??とても劇的ではない。私は、特定の言語でコードを書く方法についてのアドバイスをする場合は、一般的にパフォーマンスが低下するコンストラクトの使用を推奨すべきではないということだけです。 Pythonは再帰のために構築されておらず、新しいスタックフレームの割り当てに伴うオーバーヘッドが多く、テールコールの最適化はありません。再帰制限もあります。再帰的な実装の単純さが非再帰的な実装を上回る可能性がある、非常に深くないツリーを歩いていくような場合があります。 –

1

関数型プログラミングによって、あなたは高階関数とラムダを使用することによって意味場合:

sum(map(lambda k, v: v * stock[k], prices.items())) 

表現x[1:]が辞書ではなく、発電機を使用して、キー

-1
def total(stock): 
    return sum([v*prices[k] for k,v in stock.iteritems()]) #.iteritems() is a built in method for dicts. it returns key, value pairs 
                  #same as i, dict[i] 
1

あるので、あなたがエラーを取得します式またはリスト/セット/ディクショナリ内包表記は非常に機能的です。

In [1]: prices = { 
    ...:  "banana" : 4, 
    ...:  "apple" : 2, 
    ...:  "orange" : 1.5, 
    ...:  "pear" : 3, 
    ...: } 
    ...: stock = { 
    ...:  "banana" : 6, 
    ...:  "apple" : 0, 
    ...:  "orange" : 32, 
    ...:  "pear" : 15, 
    ...: } 
    ...: 

In [2]: total_value = sum(stock[k]*prices[k] for k in stock) 

In [3]: total_value 
Out[3]: 117.0 

In [4]: 
+0

@GuillaumeJacquenot私は編集に同意しません。インタラクティブなインタープリタセッションの出力を貼り付けることは、StackOverflowでは一般的です。最後の行はインタラクティブセッションで*のようにしか動作しないので、In/Out行を削除すると実際には非理性的になります。* –

1

あなたは(Functional Programmingを参照)あまりにも状態や突然変異を避け、副作用なしに必要な値を返すようにdict comprehensionを使用することができます。

def total(prices, stock): 
    return sum([p * stock[k] for k, p in prices.items() if k in stock]) 

>>> total(prices, stock) 
>>> 117.0 

This answerは、インスピレーションを提供します。

関連する問題