配列に数値を追加し、nil要素を無視します。私の解決策は明らかに機能しません。配列に数値を追加する際に、無限の要素を避けてください。
array = [3,4,5,6,nil,9,nil,9,3]
def add(array)
array.inject(0){|memo,s|s.is_a?Integer ? memo+=s : next}
end
配列に数値を追加し、nil要素を無視します。私の解決策は明らかに機能しません。配列に数値を追加する際に、無限の要素を避けてください。
array = [3,4,5,6,nil,9,nil,9,3]
def add(array)
array.inject(0){|memo,s|s.is_a?Integer ? memo+=s : next}
end
使用compact
array.compact.reduce(0,:+)
'reduce(0、:+)'を使用してください。そうでない場合、配列にゼロ以外の要素がない場合、 '0'ではなく' nil'を返します。 – Ursus
ありがとうございます。私は配列に無限要素があると仮定していました –
'(array- [nil])。inject(:+)' funのためだけに) –
私はそれを考え出した:
array.reject{|a| a.nil?}.inject(0){|memo,a| memo+=a}
それは動作は遅くなりますが、配列のサイズが大きくなるにつれてより遅くなります。 http://stackoverflow.com/a/42093625/128421で示されているように組み込みのメソッドを使用する方がよいでしょう。また、回答を選択しない限り、回答として「最終的な」コードを追加しない方がよいでしょう。 –
バージョンが動作しない理由は単純です:ブロックの戻り値はmemo
値となり、次の反復のために。 s
がInteger
でない場合は、何も返さない、つまりnil
なので、次の繰り返しではmemo
はnil
です。
あなたは、単にそのままメモを返すことでそれを修正することができます:
def add(array)
array.inject(0) { |memo, s| s.is_a? Integer ? memo += s : next memo }
# ↑↑↑↑
end
これはあなたの問題を解決します可能な最小の変更です。
next
が実際には必要ではないので、ブロックは通常、ブロック内で最後に評価された式の値を返します。
def add(array)
array.inject(0) { |memo, s| s.is_a? Integer ? memo += s : memo }
end
それはmemo
に割り当てる意味がありません、それはスコープの外に出ますとにかくブロックの終わりに、あなたは再びそれを使用することはありません:
def add(array)
array.inject(0) { |memo, s| s.is_a? Integer ? memo + s : memo }
end
標準コミュニティスタイルガイドによると、引数リストのメッセージに送信し、それは「手続きのような」MESでない限り、括弧で囲む必要がありますセージ送信(例: puts
、require
)または "キーワードのような" 一(例えばattr_accessor
):
def add(array)
array.inject(0) { |memo, s| s.is_a?(Integer) ? memo + s : memo }
end
が個人的に、私は、条件演算子が好きではありません。それはしかし、文体の問題だが、私はずっとこれを好む:あなたが反復する前に
はdef add(array)
array.inject(0) { |memo, s| if s.is_a?(Integer) then memo + s else memo end }
end
しかし、はるかに簡単に解決策はnil
の要素を削除することです:
def add(array)
array.reject {|s| s.nil? }.inject(0) { |memo, s| memo + s }
end
def add(array)
array.reject(&:nil?).inject(0) { |memo, s| memo + s }
end
しかし、実際にはより読みやすいとちょうど同じです。
def add(array)
array.compact.inject(0) { |memo, s| memo + s }
end
あなたがSymbol
として組み合わせる方法の名前を渡すことができます:
def add(array)
array.compact.inject(0, :+)
end
そして、それはちょうど同じsum
の通りです:あなたはそれを行うことができます
def add(array)
array.compact.sum
end
それは誰も怠け者と呼ぶことのできない人です –
多くの方法:
array = [3,4,5,6,nil,9,nil,9,3]
array.sum(&:to_i) # => 39
array.reject(&:nil?).sum # => 39
あなたがcompact
代わりのreject(&:nil?)
使用することができます。
array.compact.sum # => 39
、あなたが合理的に最近のRubyを使用している必要がある場合は利用可能sum
を、持っていない場合は、inject(:+)
使用することができます。
array.compact.inject(:+) # => 39
require 'fruity'
compare do
sum_to_i { array.sum(&:to_i) }
reject_nil { array.reject(&:nil?).sum }
compact_reduce { array.compact.reduce(0,:+) }
compact_sum { array.compact.sum }
compact_inject { array.compact.inject(:+) }
do_not_do_this { array.reject{|a| a.nil?}.inject(0){|memo,a| memo+=a} }
end
# >> Running each test 8192 times. Test will take about 1 second.
# >> compact_sum is faster than compact_inject by 10.000000000000009% ± 10.0%
# >> compact_inject is similar to compact_reduce
# >> compact_reduce is faster than sum_to_i by 19.999999999999996% ± 10.0%
# >> sum_to_i is faster than reject_nil by 1.9x ± 0.1
# >> reject_nil is faster than do_not_do_this by 2.0x ± 0.1
Jörg's solutionは明らかに最も高速です。
'next'を使う代わりに' memo'を3者の最後の部分に返すだけです。また、injectでは、 'memo + = s'は' memo + s'と同じですので、ここで等号は実際には重複しています。 –