2009-09-02 10 views
7

私は|| =演算子を知っていますが、ここで助けてくれるとは思わない...作成しようとしていますオブジェクトの配列の中の「型」の数を数える配列。Ruby:変数を0に設定する方法、または既に変数が設定されている場合は1を加算する方法

array.each do |c| 
    newarray[c.type] = newarray[c.type] ? newarray[c.type]+1 ? 0 
end 

もっと優雅な方法がありますか?

+1

2番目の疑問符はコロンである必要があります。 – jonas054

答えて

14
types = Hash.new(-1) # It feels like this should be 0, but to be 
        # equivalent to your example it needs to be -1 
array.each do |c| 
    types[c.type] += 1 
end 
+0

+1 –

2

||=は助けを行います。

types = {} 
array.each do |c| 
    types[c.class] ||= 0 
    types[c.class] += 1 
end 
+2

これは最初に1に設定されます... newarray [c.type] || = -1 newarray [c.type] + = 1 –

+0

はい、そうではありませんか?たとえば、arrayが[1]の場合、型は{Fixnum => 1}になります。そして私たちは1つのFixnumを持っています。 –

+0

!types [c.class]の場合、ループの終わりに0に設定する必要があります(1ではなく)。 – Chuck

4
array.each do |c| 
    newarray[c.type] = 1 + (newarray[c.type] || -1) 
end 

また

array.each do |c| 
    newarray[c.type] ||= -1 
    newarray[c.type] += 1 
end 
+1

私はあなたの第二のものが好きです。唯一の欠点は、後に来る人が間違いのために取るかもしれないことのようなものだということです。プロダクションでそれを使用している場合、私はなぜそれをやっているのかを説明する簡単なコメントを追加したいと思います。 – Pesto

+0

私は第二の方法が好きです。これは2行であり、潜在的に2つの代入ですが、複雑な条件文や1行には何も表示されません。コメントのために+1 – Chuck

6

インデックスが存在しない場合は、デフォルト値を提供することができるためArray#fetch方法を使用します

array.each do |c| 
    newarray[c.type] = newarray.fetch(c.type, -1) + 1 
end 
0

あなたの変数newarrayは、Rubyや他の多くの言語では、配列がClassのようなランダムオブジェクトではなく、整数でインデックス付けされているので、おかしな名前が付けられています。これはおそらくHashです。

また、c.typeの代わりにc.classを使用する必要があります。これは廃止予定です。あなたがHashを作成しているので、

最後に、あなたがそうのようなinjectを使用することができます。

newarray = array.inject({}) do |h,c| 
    h[c.class] = h.key?(c.class) ? h[c.class]+1 : 0 
    h 
end 

あるいは、ワンライナー用:

newarray = array.inject({}) { |h,c| h[c.class] = h.key?(c.class) ? h[c.class]+1 : 0 ; h } 

あなたが見ることができるように、これは与えます望ましい結果:

irb(main):001:0> array = [1, {}, 42, [], Object.new(), [1, 2, 3]] 
=> [1, {}, 42, [], #<Object:0x287030>, [1, 2, 3]] 
irb(main):002:0> newarray = array.inject({}) { |h,c| h[c.class] = h.key?(c.class) ? h[c.class]+1 : 0 ; h } 
=> {Object=>0, Hash=>0, Array=>1, Fixnum=>1} 
0

Ruby 1.8.7以降では、配列の各リストをcount-1に変換し、配列のハッシュをmapが返すようにします。

Hash[array.group_by(&:class).map { |k,v| [k, v.size-1] }] 
関連する問題