問題
こんな配列を、
[1, 2, 3]
こうしたい。
[1, 1, 2, 2, 3, 3]
どういう書き方があるんだろう?
・・・という話題が某所で挙がったので、いくつかイディオムを考えてみました。
#map
よくあるアイデアはmap
を使う方法かもしれません。
[1, 2, 3].map{|v| [v, v]}.flatten #=> [1, 1, 2, 2, 3, 3]
しかし、もっといいメソッドがあります。
#flat_map
map
+ flatten
するなら、その名もズバリ、flat_map
というメソッドが使えます。
[1, 2, 3].flat_map{|v| [v, v]} #=> [1, 1, 2, 2, 3, 3]
#zip
しかし、個人的に一番好きなのはzip
を使って宣言的に書く方法です。
array = [1, 2, 3]
array.zip(array).flatten #=> [1, 1, 2, 2, 3, 3]
変数への格納とflatten
をなくせるともっとカッコいいんですが。
RSpecで確認する
ちゃんとテストも書いて確認しましょうね~。
describe 'duplicate each item' do
let(:array) { [1, 2, 3] }
shared_examples 'duplicate each item' do
it { should eq [1, 1, 2, 2, 3, 3] }
end
describe 'use map' do
subject { array.map{|v| [v, v]}.flatten }
it_behaves_like 'duplicate each item'
end
describe 'use flat_map' do
subject { array.flat_map{|v| [v, v]} }
it_behaves_like 'duplicate each item'
end
describe 'use zip' do
subject { array.zip(array).flatten }
it_behaves_like 'duplicate each item'
end
end
まとめ
他にもいろいろやり方はあると思いますが、上の3つぐらいが一番シンプルかな~と思います。
「もっと短くてクールなイディオムがあるぜ!」という方は、ぜひコメントをお願いします~。