0

重複の可能性:
ruby配列内の重複要素をカウントします

私はルビーを学び始めたばかりで、このようなことを達成したいと思っています。配列があるとしましょう

["student", "student", "teacher", "teacher", "teacher"]

私がやろうとしているのは、生徒と教師の数を数えてハッシュに保存することです。

{:student= > 2, :teacher=> 3}

誰かが私にこれを行う方法について何らかの指示を与えることができますか?

4

7 に答える 7

3

この答えを確認する必要があります。これにより、次の例が得られます。

# sample array
a=["aa","bb","cc","bb","bb","cc"]

# make the hash default to 0 so that += will work correctly
b = Hash.new(0)

# iterate over the array, counting duplicate entries
a.each do |v|
  b[v] += 1
end

b.each do |k, v|
  puts "#{k} appears #{v} times"
end
于 2012-11-11T08:04:16.907 に答える
1
list = ["student", "student", "teacher"]

# Initializing the hash with value 0 so that we can use += 1
count = Hash.new(0)  

list.each {|el| count[el] += 1}

#Number of student  
count['student']
于 2012-11-11T08:03:33.260 に答える
1
xs.inject({}) { |acc, x| acc.update(x => (acc[x] || 0) + 1) }
#=> {"student"=>2, "teacher"=>3} 

または:

xs.each_with_object(Hash.new(0)) { |x, acc| acc[x] += 1 }
#=> {"student"=>2, "teacher"=>3}
于 2012-11-11T12:22:09.807 に答える
1

この特定の問題は、適切なアルゴリズムを選択する方法の優れた例ですが、さらに重要なことに、適切なデータ構造によってソリューションを大幅に簡素化できます。実際、この特定のケースでは、適切なデータ構造を選択すると、アルゴリズムが非常に簡単になり、基本的に完全に消滅します。データ構造すでに答えです。

私が話しているデータ構造はMultiset:aMultisetに似てSetいますが、一意のアイテムだけを格納するのではなく、各アイテムがに含まれる頻度のカウントを格納する点が異なりますMultiset。基本的に、Setは特定のアイテムがに含まれているかどうかSet 示し、Multisetさらにその特定のアイテムがに含まれている頻度Multisetも示します。

残念ながら、MultisetRubyコアライブラリまたは標準ライブラリには実装がありませんが、Web上にいくつかの実装があります。

あなたは文字通りあなたMultisetからを構築する必要がありますArray。次に例を示します。

require 'multiset'

ary = ["student", "student", "teacher", "teacher", "teacher"]

print Multiset[*ary]

はい、それだけです。これは印刷します:

#2 "student"
#3 "teacher"

以上です。例、https ://GitHub.Com/Josh/Multimap/を使用:

require 'multiset'

histogram = Multiset.new(*ary)
# => #<Multiset: {"student", "student", "teacher", "teacher", "teacher"}>

histogram.multiplicity('teacher')
# => 3

例、 http: //maraigue.hhiro.net/multiset/index-en.phpを使用:

require 'multiset'

histogram = Multiset[*ary]
# => #<Multiset:#2 'student', #3 'teacher'>

もう1つの可能性は、を使用することHashです。これは、基本的にMultiset、要素のカウントを処理する代わりに、自分で実行する必要があることを意味します。

histogram = ary.inject(Hash.new(0)) {|hsh, item| hsh.tap { hsh[item] += 1 }}
print histogram
# { "student" => 2, "teacher" => 3 }

Enumerable#group_byただし、自分で数える代わりに、要素を自分でグループ化してから、グループ化をそれらのサイズにマップすることで、これを簡単に行うことができます。最後に、に変換し直しますHash

Identity = ->x { x }

print Hash[[ary.group_by(&Identity).map {|n, ns| [n, ns.size] }]
# { "student" => 2, "teacher" => 3 }
于 2012-11-11T13:08:05.750 に答える
0

それは本当にここSOで死ぬまで行われていますが、私は提案します:

Hash[*a.group_by{|x| x}.flat_map{|k, v| [k.to_sym,v.size]}]
#=> {:student=>2, :teacher=>3}
于 2012-11-11T08:43:06.830 に答える
0
a = ["student", "student", "teacher", "teacher", "teacher"]

a.inject({}){|h, e| h[e] ||= a.count(e); h}
# => {"student"=>2, "teacher"=>3}
于 2012-11-11T09:38:39.653 に答える
0
list = ["student", "student", "teacher", "teacher", "teacher"] #original list

counts = {} #where the count hash will be

list.uniq.map{|x| counts[x]= list.count(x)} 

リスト内のすべての一意のアイテムについて、元のリストからのカウントをカウントハッシュに入れます。

1行。清潔でシンプル。

于 2012-11-11T09:50:02.337 に答える