查找Ruby数组的模式(简体_

问题描述 投票:0回答:6

我正在尝试找到数组的模式。模式=出现频率最高的元素。

我知道#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)
ruby arrays hash
6个回答
0
投票
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] 

给出哈希值排序后的集合中的最后一个条目,它应该是您的模式。请注意,可能有多种模式,因此您可以向后迭代,同时值部分保持恒定以确定它们全部。


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]


0
投票
此后,您计划通过将哈希中关联键的值对每个实例增加一个来对数组中每个值的实例进行计数。因此,在数组中找到数字1之后,哈希看起来像这样:{1: 1, 2: 0, 3: 0}。您显然需要对数组中的每个值执行此操作,因此鉴于您的方法和当前的理解水平,我建议再次遍历数组:

array.each do |x| myhash[x] += 1 end

如您所见,由于我们已经为数组中的每个数字创建了一个key:value对,因此我们不需要检查myhash[k] == array[x]

但是,尽管这种方法行之有效,但效率不是很高:我们必须遍历数组两次。第一次将所有key:value对初始化为某个默认值(在这种情况下为零),第二次将每个数字的频率计数。

由于每个键的默认值为零,我们可以通过使用其他哈希构造函数来消除初始化默认值的需要。如果我们访问不存在的键,myhash = {}将返回nil,但是如果我们访问不存在的键,myhash = Hash.new(0)将返回0(请注意,如果需要,您可以提供任何其他值或变量)。

通过提供默认值零,我们可以完全摆脱第一个循环。当第二个循环找到不存在的键时,它将使用提供的默认值并自动对其进行初始化。


0
投票

0
投票
test = [1, 2, 3, 3, 3, 4, 5, 6, 6, 6] test.modes #=> [3, 6]

0
投票
array = array.sort!

然后使用排序后的数组创建哈希默认值0,并将数组的每个元素作为键,并将出现的次数作为值

hash = Hash.new(0)
array.each {|i| hash[i] +=1 }

然后,如果哈希按值(出现次数)的降序排序,则第一个元素将是>

mode = hash.sort_by{|key, value| -value}.first[0]

© www.soinside.com 2019 - 2024. All rights reserved.