やったこと
keep_if
を使ってみます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
調査
$ irb
irb(main):001:0> a = %w[a b c d]
irb(main):002:0> a.keep_if {|v| v == 'a' || v == 'd'}
=> ["a", "d"]
block のなかで false
判定の要素を削除します。
ちなみに Array#select!
Array#filter!
でも同じことが出来ます。
irb(main):004:0> a = %w[a b c d]
irb(main):005:0> a.select! {|v| v == 'a' || v == 'd'}
=> ["a", "d"]
irb(main):006:0> a
=> ["a", "d"]
...
irb(main):009:0> a = %w[a b c d]
irb(main):010:0> a.filter! {|v| v == 'a' || v == 'd'}
=> ["a", "d"]
irb(main):011:0> a
=> ["a", "d"]
少し深ぼってみます
# Equivalent to Set#keep_if, but returns nil if no changes were
# made. Returns an enumerator if no block is given.
def select!(&block)
block or return enum_for(__method__) { size }
n = size
keep_if(&block)
self if size != n
end
# Equivalent to Set#select!
alias filter! select!
削除対象があるかどうかで、違いがあるようですね。
irb(main):012:0> a = %w[a b c d]
irb(main):013:0> a.filter! {|v| true }
=> nil
irb(main):014:0> a = %w[a b c d]
irb(main):015:0> a.keep_if {|v| true }
=> ["a", "b", "c", "d"]
コメントにある通り、削除対象がない場合に nil
を返すのか self
を返すのかで挙動が違うことが分かりました。