LoginSignup
0
0

More than 5 years have passed since last update.

rubyのArray#compact!でnilを返させない

Last updated at Posted at 2016-12-06

はじめに

rubyのArrayにはcompactと呼ばれる配列中のnilを消すメソッドが定義されていますが
nilのある無いにかかわらず配列に対してのcompactは「nilの無い配列」が返ります
しかしながら破壊的メソッドであるcompact!では
「nilのある配列」に対してのcompact!は「nilの無い配列」が返りますが
「nilの無い配列」に対してのcompact!は「nil」が返ります

前回からの変更が無いときは例外を出す見たいな時は便利ですが
統一性が無いので思わぬ動作を引き起こしかねない気もします
ってことでこの記事では専用の関数を作ります

(訂正)

compactが統一性がない」という記述になってましたが
統一性がないのは「compact!」です
ご指摘ありがとうございました

実例

compact1.rb
a=[60,21,nil,'foo',nil,0,'']
p a.compact!
p a.compact!
p a
実行結果
[60, 21, "foo", 0, ""]
nil
[60, 21, "foo", 0, ""]

このように気持ち悪い結果となります
そこでcompact2を定義してみました

compact2.rb
class Array
  def compact2!
    delete_if{|item| item.nil?}
  end
end

a=[60,21,nil,'foo',nil,0,'']
p a.compact2!
p a.compact2!
p a
実行結果
[60, 21, "foo", 0, ""]
[60, 21, "foo", 0, ""]
[60, 21, "foo", 0, ""]

いい感じですね
ついでなので空文字列も消しちゃいましょう

compact2b.rb
class Array
  def compact2!
    delete_if{|item| item.nil? || item==''}
  end
end

a=[60,21,nil,'foo',nil,0,'']
p a.compact2!
p a.compact2!
p a
実行結果
[60, 21, "foo", 0]
[60, 21, "foo", 0]
[60, 21, "foo", 0]

消えたことは消えたのですがdelete_ifの書き方が少し気持ち悪い気もします
blank?かempty?が使えればもっとうまく書けそうですが
文字列にしか使えない(Undefined Method Error)なので仕方なさそうです
(個人的には,正規表現によるフィルタなど,拡張しやすい形なので,それはそれでいいのではないかと思っています)

0
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0