我试图找到一个数组的模式。 Mode =出现频率最高的元素。
我知道#enumerable有很多技巧,但我的学习中还没有。我所做的练习假设我可以在不理解可枚举的情况下解决这个问题。
我已经写出了我的游戏计划,但我仍然坚持第二部分。我不确定是否可以将哈希键与数组进行比较,如果找到则增加该值。
def mode(array)
# Push array elements to hash. Hash should overwrite dup keys.
myhash = {}
array.each do |x|
myhash[x] = 0
end
# compare Hash keys to Array. When found, push +=1 to hash's value.
if myhash[k] == array[x]
myhash[k] += 1
end
# Sort hash by value
# Grab the highest hash value
# Return key(s) per the highest hash value
# rejoice!
end
test = [1, 2, 3, 3, 3, 4, 5, 6, 6, 6]
mode(test) # => 3, 6 (because they each appear 3 times)
答案 0 :(得分:1)
有许多方法可以做到这一点。这里有几个。
<强>#1 强>
array = [3,1,4,5,4,3]
a = array.uniq #=> [3, 1, 4, 5]
.map {|e| [e, array.count(e)]}
#=> [[3, 2], [1, 1], [4, 2], [5, 1]]
.sort_by {|_,cnt| -cnt} #=> [[3, 2], [4, 2], [1, 1], [5, 1]]
a.take_while {|_,cnt| cnt == a.first.last}
#=> [[3, 2], [4, 2]]
.map(&:first) #=> [3, 4]
<强>#2 强>
array.sort #=> [1, 3, 3, 4, 4, 5]
.chunk {|e| e}
#<Enumerator: #<Enumerator::Generator:0x000001021820b0>:each>
.map { |e,a| [e, a.size] } #=> [[1, 1], [3, 2], [4, 2], [5, 1]]
.sort_by { |_,cnt| -cnt } #=> [[4, 2], [3, 2], [1, 1], [5, 1]]
.chunk(&:last)
#<Enumerator: #<Enumerator::Generator:0x00000103037e70>:each>
.first #=> [2, [[4, 2], [3, 2]]]
.last #=> [[4, 2], [3, 2]]
.map(&:first) #=> [4, 3]
<强>#3 强>
h = array.each_with_object({}) { |e,h|
(h[e] || 0) += 1 } #=> {3=>2, 1=>1, 4=>2, 5=>1}
max_cnt = h.values.max #=> 2
h.select { |_,cnt| cnt == max_cnt }.keys
#=> [3, 4]
<强>#4 强>
a = array.group_by { |e| e } #=> {3=>[3, 3], 1=>[1], 4=>[4, 4], 5=>[5]}
.map {|e,ees| [e,ees.size]}
#=> [[3, 2], [1, 1], [4, 2], [5, 1]]
max = a.max_by(&:last) #=> [3, 2]
.last #=> 2
a.select {|_,cnt| cnt == max}.map(&:first)
#=> [3, 4]
答案 1 :(得分:0)
在您的方法中,您首先初始化一个包含从数组的唯一值中获取的键的哈希值,并将关联的值全部设置为零。例如,数组[1,2,2,3]
将创建哈希{1: 0, 2: 0, 3: 0}
。
在此之后,您计划通过将散列中关联键的值递增1来为每个实例计算数组中每个值的实例。因此,在数组中找到数字1
后,哈希看起来如此:{1: 1, 2: 0, 3: 0}
。你显然需要对数组中的每个值执行此操作,因此根据您的方法和当前的理解水平,我建议再次循环遍历数组:
array.each do |x|
myhash[x] += 1
end
如您所见,我们不需要检查myhash[k] == array[x]
,因为我们已经为数组中的每个数字创建了一个键:值对。
然而,虽然这种方法可行,但效率不高:我们不得不两次遍历数组。第一次将所有键:值对初始化为某个默认值(在本例中为零),第二次将每个数字的频率初始化。
由于每个键的默认值都是零,我们可以通过使用不同的哈希构造函数来删除初始化默认值的需要。如果我们访问不存在的密钥,myhash = {}
将返回nil
,但如果我们访问不存在的密钥,myhash = Hash.new(0)
将返回0
(请注意,您可以提供任何其他值或变量,如果需要)。
通过提供默认值零,我们可以完全摆脱第一个循环。当第二个循环找到不存在的密钥时,它将使用提供的默认值并自动初始化它。
答案 2 :(得分:0)
您可以创建hash with a default initial value:
myhash = Hash.new(0)
然后增加特定事件:
myhash["foo"] += 1
myhash["bar"] += 7
myhash["bar"] += 3
p myhash # {"foo"=>1, "bar"=>10}
有了这样的理解,如果你替换你的初始哈希声明,然后在你的array.each
迭代器中进行递增,那么你已经完成了。
myhash.sort_by{|key,value| value}[-1]
给出排序的哈希值集合中的最后一个条目,它应该是您的模式。请注意,可能有多种模式,因此您可以向后迭代,同时值部分保持不变以确定所有模式。
答案 3 :(得分:0)
def mode(array)
array.group_by{ |e| e }.group_by{ |k, v| v.size }.max.pop.map{ |e| e.shift }
end
答案 4 :(得分:0)
使用simple_stats
gem:
test = [1, 2, 3, 3, 3, 4, 5, 6, 6, 6]
test.modes #=> [3, 6]
答案 5 :(得分:0)
如果它是未排序的数组,我们可以按降序对数组进行排序
array = array.sort!
然后使用排序后的数组创建哈希默认值0,并将数组中的每个元素作为键,并将出现的次数作为值
hash = Hash.new(0)
array.each {|i| hash[i] +=1 }
如果哈希值按值(出现次数)的降序排列,则模式将是第一个元素
mode = hash.sort_by{|key, value| -value}.first[0]