查找数组的模式

时间:2014-04-24 19:50:50

标签: ruby

所以我正在研究Ruby Cookbook的Mean Median and Mode章节,我正在试图弄清楚为什么代码正在做它正在做的事情。我得到了其他一切,但是添加到变量模式然后(从它的外观)重新分配是什么?我知道代码块中所有运算符的含义,但我无法理解它背后的逻辑。

def modes(array, find_all  = true)
  histogram = array.inject(Hash.new(0)) {|h,n| h[n] += 1; h  }
  modes = nil 

  histogram.each_pair do |item, times| 
    modes << item if modes && times == modes[0] and find_all
    modes = [times, item] if (!modes && times >1) or (modes && times > modes[0])
  end

  return modes ? modes[1...modes.size] : modes
end

1 个答案:

答案 0 :(得分:2)

首先,不要将此代码看作是模拟的内容。它存在很多问题并且非常脆弱,我坦率地说它无法相信它已被发表。

以下是主要问题:

  1. modes是方法的名称方法中临时变量的名称
  2. 内部modes有时是零,有时是数组,each_pair块中每行的行为会根据哪个更改。
  3. modes数组的第一个值用于存储另一个临时变量
  4. modes数组的其余值用作返回值。
  5. 最终的return语句再次检查 modesnil,如果没有,则返回尾部,如果是,则返回nil。从方法中返回nil通常是一个好主意。它可能会在许多其他地方破坏你的其他代码,并且会让你必须在所有地方执行所有这些零检查 - 总之,它会使程序的其余部分看起来像这种可怜的方法。
  6. 它使用控制流运算符andor代替布尔运算符&&||作为布尔条件
  7. 至于你的问题,我认为混淆来自这四行:

    histogram.each_pair do |item, times| 
      modes << item if modes && times == modes[0] and find_all
      modes = [times, item] if (!modes && times >1) or (modes && times > modes[0])
    end
    

    这循环遍历每对histogram哈希,如下所示:

    1. modes是否存在? times与第一个元素相等吗?我应该find_all吗?
      • 如果是,请将当前item添加到数组的末尾。
      • 否则,什么都不做
    2. 以下其中一项是真的吗?
      • modesnilitem被多次发现
      • modes不是niltimes的当前值大于其第一个元素
      • 如果是,请将modes的当前值替换为[times, item]
      • 否则,什么也不做。