Ruby inject (Enumerable) メソッドを学ぶ
概要
お題を通して Ruby で inject メソッドを学びました。その備忘録です。
お題
123,456 円を紙幣・硬貨が一番少なくなる様になる組み合わせを求めてください。
硬貨 … 1, 5, 10, 50, 100, 500 円玉
紙幣 … 1000, 2000, 5000, 10000 円札
答え
- 10,000 円札 × 12
- 5,000 円札 × 0
- 2,000 円札 × 1
- 1,000 円札 × 1
- 500 円玉 × 0
- 100 円玉 × 4
- 50 円玉 × 1
- 10 円玉 × 0
- 5 円玉 × 1
- 1 円玉 × 1
inject メソッド
配列の組み合わせで答えを出すとシンプルに書けます。
大きい値から順に divmod の結果 [商, 余り]
を不定数個の配列 (a) の後ろに足して、
r に配列の一番後ろの要素 余り
が入るので、それ次の iterator の計算に利用する方法です。
1 | [] + 123456.divmode(10000) # [12, 3456] |
最後の 0 が余計ですが、非常にシンプルな形で答えを求られました。
ただ、
この inject の計算式が初手でスッと出すのは慣れが必要な印象。
なので、
一旦 each で計算の手順を確認してから inject でコードがシンプルになりそうならやってみる、
っていうのが慣れるのに良さそうでした。
each メソッド
each でやると loop の外側で b = []
と最終的に返す配列を定義する必要があります。
b << r if p.size - 1 == index
は、不要ですが、回答の配列を inject メソッドの場合と合わせました。
benchmark とってみる
1 | require "benchmark" |
each の方が速かったです。
1 | user system total real |
個人的には inject の方が速くなってくれると本記事が締まったんですが
今回の計算ロジックでは、each の方がパフォーマンスがよかったです。
hash を扱ってみる
inject
each
benchmark とると、 each, hash どちらもほぼ同等でした。
まとめ
inject メソッドを例題を通して学びました。
例題では特にシンプルに書けましたが、パフォーマンスが格段に上がるという話ではないので
使い所は見定める必要があるかなと思いました。
以上
ご参考になれば幸いです。
Ruby inject (Enumerable) メソッドを学ぶ
https://kenzo0107.github.io/2019/11/25/2019-11-26-ruby-inject-enumerable/