はじめに
Array#minimax
というメソッドがRuby 2.4から導入されていて、そのメソッドの実装を読んでいた時に思いついたArray#both_end
メソッドの実用例についてつらつらと書いてみた記事。
なので、実際にRubyにそういうメソッドがあるわけではない。
実装
/* * call-seq: * ary.both_end -> new_ary * ary.both_end(n) -> new_ary * * Returns the last element(s) of +self+. If the array is empty, * the first form returns +nil+. * * See also Array#first for the opposite effect. * * a = [ "w", "x", "y", "z" ] * a.both_end #=> ["w", "z"] * a.both_end(2) #=> [["w", "x"], ["y", "z"] * [].both_end #=> [nil, nil] */ static VALUE rb_ary_both_end(int argc, VALUE *argv, VALUE ary) { VALUE first, last; rb_check_arity(argc, 0, 1); if (RARRAY_LEN(ary) == 0) return rb_assoc_new(Qnil, Qnil); first = rb_ary_first(argc, argv, ary); last = rb_ary_last(argc, argv, ary); return rb_assoc_new(first, last); }
実装はこんな感じで、内部のコードではArray#first
とArray#last
を呼び出してる。最後にrb_assoc_new
で新しくArray
を作って返している。
空のArray
の場合は[nil, nil]
が返えるようになっている。
現状の使いどころ
Array
の両端の値を指定の数だけとってきたい時に使う感じ
ary = [1, 2, 3, 4, 5] result = ary.both_end(2) puts result.first == [1, 2] # => true puts result.last == [4, 5] # => true
あとはこんな感じでArrayの両端を使った繰り返し書くときとか?
ary = [1, 2, 3, 4, 5] result = ary.both_end(2) result[0].map{|a1| result[1].map{|a2| puts a1 == a2 } }
Railsとかで使う場合は、最新と最古のデータとってきたい時に一行で書けるかもしれない?
@result = Topic.both_end(3) # => 最新と最古のデータを三件づつとってくるイメージ
現状の問題点?
内部の実装でArray#first
とArray#last
を使っているのでこういうコードはエラーにならない。
ary = [1, 2, 3, 4, 5] result = ary.both_end(10) # => [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
エラーになった方が自然なのかどうなのかは判断できなかったので、そのままにしてるけどエラーのほうが良いのだろうか?
まあ、要素が同じArray
を複数持つことができるのでエラーにならない方が恩恵ありそうかも。
ary = [1, 2, 3, 4, 5] result = ary.both_end(10) # => [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5]] a1 = result.first a2 = result.last # => [1, 2, 3, 4, 5]がそれぞれに入る
まとめ
とりあえず、最新と最古のデータとってきたりするときには使えそうかなぁという感じ。 今後も仕様とか検討してみるけど、提案するかはまだ保留。
もし、記事を読んだ方で興味のある方はコメントとかいただけると助かります