像间隔一样使用哈希值

时间:2014-04-02 08:06:27

标签: ruby hashmap

我有这段代码:

@counter = 719    

@period_hash = {
  :sunset => 360,
  :day    => 720,
  :dawn   => 1200,
}

@period = :nothing

def init_period
  periods = @period_hash.keys
  @period_hash.each_with_index do |(__, number), index|
    if @counter < number
      @period = periods[index - 1]
      break
    end
  end
  if @period == :nothing
    @period = periods[-1]
  end
end

init_period
p @period

我有一个@counter,其值介于0到1440之间。 然后我有一个可变内容的哈希。内容将始终为symbol =&gt;整数 整数值也是0到1440之间的数字,所有数字都是唯一的 哈希。哈希将被排序,因此最低的数字将是第一个和最高的数字 将是最后一次。

然后我有一个方法(init_period),它将返回与@counter变量对应的键。 这些是@counter和返回符号的间隔:

0    ..  359  =>   :dawn
360  ..  719  =>   :sunset
720  ..  1199 =>   :day
1200 ..  1440 =>   :dawn

一切正常,但我想知道是否有其他更好的方法来做同样的事情。

1 个答案:

答案 0 :(得分:0)

您可以使用以下代码将哈希转换为不同的结构。目前还不是很清楚,因为您正在使用@period_hash以外的信息(如全局范围边界以及必须重复使用最后一个值的事实)。

hash = @period_hash.
  keys.
  unshift(@period_hash.keys.last).   # reuse last key from hash
  zip(                               # zip keys with ranges
    [0, *@period_hash.values, 1440]. # add 0 and 1440 as boundaries
    each_cons(2)                     # convert array to consecutive pairs enum
  ).each_with_object({}) {|(key, (from, to)), hash|
    hash[from...to] = key            # build actual hash
  }

在此结构上,您可以调用将检测您的期间的代码:

hash.detect {|a,b| a.include?(719) }

你最终得到了真正难以理解的代码。如果您的期间不会经常变化,您可以使用非常易读的代码:

def init_period(counter)
  case counter
  when 0...360     then :dawn
  when 360...720   then :sunset
  when 720...1200  then :day
  when 1200...1440 then :dawn
  end
end

这种方式的时间边界不是从外部结构中获取的,但代码是显而易见的。