😽

Grow.rbのmy_inject問題を解いてみる

2025/01/02に公開

Grow.rbとは:

Ruby力を高めたいRubyistたちが、コードを書いたりちょっとマニアックな内容を学んだりするコミュニティです。

RubyのinjectメソッドをRubyで作ってみようというテーマです。

テストコードはこちら。

https://github.com/grow-rb/enumerable-exercises/blob/d08568e5319c9d24a74c9cb635ed1115ad43adc3/inject/inject_test.rb#L1-L24

書いた回答がこちら。eachのみを使う縛り。

module Enumerable
  def my_inject(initial_value = nil, sym = nil, &block)
    if sym
      block = sym.to_proc
    elsif initial_value.is_a?(Symbol) #シンボルだけ、初期値なしで渡されたとき
      block = initial_value.to_proc
      initial_value = nil
    end

    # 初期値がない場合、渡された要素の先頭を初期値とする
    accumulator = initial_value.nil? ? first : initial_value

    drop(initial_value.nil? ? 1 : 0).each do |el|
      accumulator = block.call(accumulator, el)
    end

    accumulator
  end
end

ちょっと難しかったので、AIの協力をもとに書いた。ポイントとしては、

  • シンボルを受け取ったらそれをProcにする
  • 初期値が渡されなかったら、要素の先頭を初期値にする
  • 初期値がなければ、先頭の要素が初期値として使われるため、その場合はdrop(1)をする

このGrow.rbシリーズだと一番むずかしかったかも。
個人的に、injectは「配列内の要素(主に数値)をあれこれして合計値を返す」というイメージが強かったのだけど、テストコードを見てのとおり、もっといろんなことに使えることが知れておもしろかった。たたみ込み演算は奥が深い。

Discussion