1

Rubymonk コーディング演習ソリューションの理解に取り組んでいますが、costメソッドで何が起こっているのかを理解するのに苦労しています。

参考までに、menu{:rice => 3, :noodles => 2}から注文の総コストを計算するためのものmenuです。

注文例は次のとおりです。

{:rice => 1, :noodles => 1} )

私が思いついた解決策は、少なくとも私の頭の中ではより単純でしたが、「シンボルを整数に変換できません」というエラーが返され、それを修正できませんでしたto_i

    class Restaurant
  def initialize(menu)
    @menu = menu
  end

  def cost(*orders)
    orders.inject(0) do |total_cost, order|
      total_cost + order.keys.inject(0) {|cost, key| cost + @menu[key]*order[key] }
    end
  end
end

誰かがメソッドの各ステップをcost簡単に説明できますか?

4

3 に答える 3

0

あなたの投稿の定義の鍵costは明らかにinject方法です。このinjectメソッドは としても呼び出すことができreduceます。これは、リストを取り、それを 1 つの値に縮小するため、多くの英語話者にとってより適切な名前です。(さらに混乱させるために、関数型プログラミングの文献では、この関数はほとんどの場合「fold」と呼ばれます)。

多くの例があります。整数のリストの合計を見つけることを検討してください。

[1,2,3,4,5].inject(0) {|sum, num| return sum + num}  #=> 15

それで、ここで何が起こっているのですか?ブロックの最初の引数は、実行結果 (この場合は部分和) です。に引数として渡すものとして開始されますinject。上記の例では 0 です。

ブロックはリスト内の項目ごとに 1 回呼び出され、現在の項目が 2 番目の引数になります。ブロックによって返される値は、ブロックの次の反復に対する実行中の値 (最初の引数) になります。

したがって、上記のインジェクションをより明示的な命令コードに拡張すると、次のようになります。

def block(sum, num) 
   return sum + num
end

result = 0
for i in [1,2,3,4,5]
  result = block(result, i)
end

この知識を武器に、次のことに取り組みましょうcost

 def cost(*orders)
   orders.inject(0) do |total_cost, order|
     total_cost + order.keys.inject(0) {|cost, key| cost + @menu[key]*order[key] }
   end
 end

returnまず、 Ruby では省略できるという事実を利用しています。ブロック内の最後の式の値は、ブロックの戻り値です。

どちらinjectの呼び出しも、上記の例によく似ています。単純な合計ループです。外側injectは個々の注文すべての総計を作成しますが、これらの注文は数値ではなくマップであるため、それらを合計する前に各注文のコストを取得するためにさらに多くの作業を行う必要があります。その「もっと仕事を」というのが内なるinject呼びかけです。

order.keys.inject(0) {|cost, key| cost + @menu[key]*order[key] }

上記の拡張を使用すると、これがどのように機能するかがわかります。メニューに従って、注文の各値 (アイテムの数量) にそのアイテムの価格 (キー) を掛けた結果を加算するだけです。

ちなみに、値だけではなくキーと値のペアを削減することで、ブロック内の順序マップでキーを検索する必要がなくなります。inject/に初期値を渡さない場合reduce、デフォルトでゼロになるという事実を利用することもできます。

orders.inject { |grand_total, order|
  grand_total + order.inject { |subtotal, line_item|
    item, quantity = line_item
    subtotal + quantity * @menu[item]
  }
}
于 2013-11-01T04:01:46.243 に答える