0

可能重复:
计算 ruby​​ 数组中的重复元素

我刚开始学习 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

这个特殊问题是如何选择正确算法的一个很好的例子,但更重要的是正确的数据结构可以大大简化解决方案。事实上,在这种特殊情况下,选择正确的数据结构将使算法变得如此微不足道,以至于它基本上完全消失了:数据结构已经答案。

我正在谈论的数据结构是 a Multiset: aMultiset就像 a Set,除了它不只存储唯一项目,而是存储每个项目在Multiset. 基本上,aSet告诉您某个特定项目是否在 中Set 此外,aMultiset还告诉您该特定项目在 中的频率Multiset

不幸的是,Ruby 核心库或标准库中没有Multiset实现,但有几个实现在网络上流传。

你实际上只需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'>

另一种可能性是使用 a Hash,这基本上只是意味着Multiset您不必为您处理元素计数,而是必须自己做:

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

但是,如果您不计算自己,而是使用自己Enumerable#group_by对元素进行分组,然后将分组映射到它们的大小,那么您可以更容易地做到这一点。最后,转换回 a 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
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)} 

对于列表中的每个唯一项目,将其从原始列表中的计数放入计数哈希中。

一条线。干净简单。

于 2012-11-11T09:50:02.337 回答
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 回答