(1..4).collect do |x|
next if x == 3
x + 1
end # => [2, 3, nil, 5]
# desired => [2, 3, 5]
next
の条件が満たされている場合、collect
は配列にnil
を入れますが、私がやろうとしているのはno element条件が満たされた場合に返される配列。これは、返された配列でdelete_if { |x| x == nil }
を呼び出さなくても可能ですか?
(Ruby 1.8.7を使用;私のコードの抜粋はかなり抽象化されています)
メソッドがあります Enumerable#reject
これはちょうど目的に役立ちます:
(1..4).reject{|x| x == 3}.collect{|x| x + 1}
あるメソッドの出力を別のメソッドの入力として直接使用する方法はmethod chainingと呼ばれ、Rubyでは非常に一般的です。
ところで、map
(またはcollect
)は、列挙可能な入力から出力への直接マッピングに使用されます。異なる数の要素を出力する必要がある場合、Enumerable
の別のメソッドが必要になる可能性があります。
編集:要素の一部が2回繰り返されるという事実に悩まされている場合、inject
(または同様のメソッド each_with_object
):
(1..4).each_with_object([]){|x,a| a << x + 1 unless x == 3}
結果の配列で.compact
を呼び出すだけで、配列内のnilのインスタンスがすべて削除されます。既存の配列を変更したい場合(変更しない理由はありません)、.compact!
を使用します。
(1..4).collect do |x|
next if x == 3
x
end.compact!
ただの提案、なぜあなたはそれをこのようにしないのですか:
result = []
(1..4).each do |x|
next if x == 3
result << x
end
result # => [1, 2, 4]
そのようにして、別の反復を保存して、配列からnil要素を削除しました。それが役立つことを願っています=)
意思決定をヘルパーメソッドに取り込み、 Enumerable#reduce
:
def potentially_keep(list, i)
if i === 3
list
else
list.Push i
end
end
# => :potentially_keep
(1..4).reduce([]) { |memo, i| potentially_keep(memo, i) }
# => [1, 2, 4]
私は使用することをお勧めします:
(1..4).to_a.delete_if {|x| x == 3}
collect + nextステートメントの代わりに。
Ruby 2.7 +
今があります!
Ruby 2.7は、まさにこの目的のためにfilter_map
を導入しています。それは慣用的でパフォーマンスがあり、すぐに標準になると期待しています。
例えば:
numbers = [1, 2, 5, 8, 10, 13]
enum.filter_map { |i| i * 2 if i.even? }
# => [4, 16, 20]
ここに 主題に関する良い読み物 があります。
それが誰かに役立つことを願っています!