Ruby 2.7 アドベントカレンダーの14日目の記事です。
Array
Array#intersection 追加
Array#& の複数引数版です。self と引数の配列の共通の要素を含む配列を返します。
ary = [1, 1, 2, 3, 3] ary.intersection #=> [1, 1, 2, 3, 3] ary.intersection([1, 2, 3]) #=> [1, 2, 3] ary.intersection([1, 2], [2, 3]) #=> [2]
次のコードとだいたい同じ。
def intersection(*args) result = self args.each do |ary| result &= ary end result end
Enumerable
Enumerable#filter_map 追加
filter
(select
) と map
(collect
) を組み合わせたものです。
ブロックを評価した結果のうち真(nil
, false
以外の値)からなる新しい配列を返します。
[1, 2, 3, 4].filter_map { |n| n.even? ? n * 2 : nil} #=> [4, 8]
次のコードとだいたい同じ。
obj.map{...}.select(&:itself)
map{...}.compact
と似てるかもしれません。ただし、compact
が取り除くのは nil
だけですが filter_map
では false
も取り除かれます。
[true, false, nil].compact #=> [true, false] [true, false, nil].filter_map(&:itself) #=> [true]
自分は filter
ではなく select
派だったのですが、select_map
というエイリアスは無いようです。
Enumerable#tally 追加
各要素の個数を Hash で返します。
'あおはあいよりいでてあいよりあおし'.chars.tally #=> {"あ"=>4, "お"=>2, "は"=>1, "い"=>3, "よ"=>2, "り"=>2, "で"=>1, "て"=>1, "し"=>1} 'いろはにほへとちりぬるを'.chars.tally #=> {"い"=>1, "ろ"=>1, "は"=>1, "に"=>1, "ほ"=>1, "へ"=>1, "と"=>1, "ち"=>1, "り"=>1, "ぬ"=>1, "る"=>1, "を"=>1}
Enumerator
Enumerator.produce 追加
ブロックを評価した結果が次の値となるような無限にくりかえす Enumerator を返します。
引数を与えなければ初期値は nil
です。
e = Enumerator.produce(0){|i| i += 1} e.next #=> 0 e.next #=> 1 e.next #=> 2 e.next #=> 3
Ruby のドキュメントには次のような例が載っています。
# 次の火曜日を見つける require 'date' Enumerator.produce(Date.today, &:succ).detect(&:tuesday?) => #<Date: 2019-12-17 ((2458835j,0s,0n),+0s,2299161j)>
Enumerator::Lazy#eager 追加
Enumerator::Lazy オブジェクトを Enumerator にしたものを返します。
e = [1, 2, 3].lazy #=> #<Enumerator::Lazy: [1, 2, 3]> e.eager #=> #<Enumerator: #<Enumerator::Lazy: [1, 2, 3]>:each>
Enumerator::Yielder#to_proc 追加
Enumerator::Yielder#<< を呼ぶような Proc を返します。
e = Enumerator.new do |y| [1, 2, 3].each do |n| y << n end end e.entries #=> [1, 2, 3]
これを次のように書けます。
e = Enumerator.new do |y| [1, 2, 3].each(&y) end e.entries #=> [1, 2, 3]