Techioz Blog

Rubyでnil値をマッピングして削除する方法

概要

値を変更するか、値を nil に設定するマップがあります。次に、リストから nil エントリを削除したいと思います。リストを保存する必要はありません。

これが私が現在持っているものです:

# A simple example function, which returns a value or nil
def transform(n)
  rand > 0.5 ? n * 10 : nil }
end

items.map! { |x| transform(x) } # [1, 2, 3, 4, 5] => [10, nil, 30, 40, nil]
items.reject! { |x| x.nil? } # [10, nil, 30, 40, nil] => [10, 30, 40]

次のようにループを実行して、条件付きで別の配列に収集できることはわかっています。

new_items = []
items.each do |x|
    x = transform(x)
    new_items.append(x) unless x.nil?
end
items = new_items

しかし、それはそれほど慣用的なものではないようです。 nil を削除/除外して、関数をリストにマッピングする良い方法はありますか?

解決策

コンパクトを使用できます。

[1, nil, 3, nil, nil].compact
=> [1, 3] 

マップ ブロックの出力として nils を含む配列を取得し、そのブロックが条件付きで値を返そうとする場合は、コードの匂いがあり、ロジックを再考する必要があることを皆さんに思い出してもらいたいと思います。

たとえば、次のようなことをしているとします。

[1,2,3].map{ |i|
  if i % 2 == 0
    i
  end
}
# => [nil, 2, nil]

それならやめてください。代わりに、マップの前に、不要なものを拒否するか、必要なものを選択します。

[1,2,3].select{ |i| i % 2 == 0 }.map{ |i|
  i
}
# => [2]

私は、正しく処理できなかったものを取り除くための最後の努力として、コンパクトを使用して混乱をクリーンアップすることを検討しています。通常、何が起こるかわからないためです。私たちは、プログラム内でどのような種類のデータが投げ込まれているかを常に知っておく必要があります。予期しない/不明なデータは不良です。作業中の配列に nils が含まれているのを見つけたときは、その存在理由を徹底的に調べ、Ruby が nils を生成して配列を選別して削除するという時間とメモリを無駄にするのではなく、配列を生成するコードを改善できるかどうかを確認します。それらは後で。

'Just my $%0.2f.' % [2.to_f/100]