散列数组,其键是包含范围的数组

时间:2017-11-15 05:20:20

标签: arrays ruby hash range

我需要将多个ID和ID范围映射到单个值。我想将整个结构存储在一个对象中。

以下是一种明智的方法吗?通过单个整数值搜索键以返回相应值的最佳方法是什么?

large array = [
   {[3110..3220, 10200, 43680] =>   'A0300'},
   {[5200, 7100..8990, 9100..9900] => 'B0400'},
   {[17110..18121, 20160, 2210..22290] => 'C0600'}
]

4 个答案:

答案 0 :(得分:2)

存储数据的合理格式是一个简单的旧简单哈希:

input = { [3110..3220, 10200, 43680] =>  'A0300',
          [5200, 7100..8990, 9100..9900] => 'B0400',
          [17110..18121, 20160, 2210..22290] => 'C0600' }

要查找元素,可以使用大小写等于三等号。幸运的是它也是为整数实现的:

value = 7300
result = input.detect { |k, _| k.any? { |r| r === value } }
result ? result.last : nil
#⇒ "B0400"

答案 1 :(得分:1)

没有。无需像您那样将每个键值对分成不同的哈希值。此外,您正在以错误的方式使用哈希。散列键值不必是一对一的。最好有这样的东西:

{
  3110..3220 => 'A0300',
  10200 => 'A0300',
  43680 => 'A0300',
  5200 => 'B0400',
  7100..8990 => 'B0400',
  9100..9900 => 'B0400',
  17110..18121 => 'C0600',
  20160 => 'C0600',
  2210..22290 => 'C0600',
}

但我的猜测是你实际上在问一个X-Y问题,而我上面的答案对你来说仍然不是最佳解决方案。

答案 2 :(得分:1)

如果值是硬连线的,可以使用案例陈述。

def look_it_up(n)
  case n
  when 7100..8990, 9100..9900, 5200
    'B0400'
  when 17110..18121, 22100..22290, 20160
    'C0600'
  when 3110..3220, 10200, 43680
    'A0300'
  else
    nil
  end
end

look_it_up 10200 #=> "A0300"
look_it_up  9135 #=> "B0400"
look_it_up 22100 #=> "C0600"
look_it_up  3079 #=> nil

假设n在某种程度上是均匀分布的,出于效率的原因,我通过减少包含的数字来排序when子句,并且在每个when子句中,我将首先是范围,然后通过减小尺寸来排序这些范围。

如果值不一定是硬连线,可以使用find/detect,就像@mudasobwa所做的那样。

如果要执行很多查找,我建议构造一个键是整数的哈希。

def init_arr(*args)
  args.each do |*a, value|
    a.each do |e|
      if e.is_a?(Range)
        e.each { |n| @h[n] = value }
      else
        @h[e] = value
      end
    end
  end
end

然后,对于任何n@h[n]都会给出其值。例如,

@h = {}
init_arr [1..4, 8..10, 11, "cat"]
  @h #=> {1=>"cat", 2=>"cat", 3=>"cat", 4=>"cat", 8=>"cat", 9=>"cat",
     #    10=>"cat", 11=>"cat"}
init_arr [13..14, 7, "dog"]
  @h #=> {1=>"cat", 2=>"cat", 3=>"cat", 4=>"cat", 8=>"cat", 9=>"cat",
     #    10=>"cat", 11=>"cat", 13=>"dog", 14=>"dog", 7=>"dog"}

然后(说),

@h[13]
  #=> "dog"
@h[11]
  #=> "cat"
@h[12]
  #=> nil

当然,这假设@h.size是可管理的。

也可以构造一个查找数组,比如@arr,它应该比使用哈希更快(尽管它可能比哈希消耗更多的内存)。如果没有相应的值,@arr[n]会返回nnil的值。如果某些值为负数,或者最小的n非常大,则会改为写@arr[n+@offset],其中@offset是显而易见的值。

答案 3 :(得分:0)

当您想要查找给定单个值的数据时,将数组和/或范围用作散列键是没有意义的。哈希的优点是,给定密钥,您可以快速找到值。在您的情况下,您必须按顺序遍历哈希以查找条目。在这种情况下,使用对数组更有意义,第一个组件描述范围,第二个组件描述ID。

如果要使用哈希,则应为每个可能的整数值创建相应的条目。

如果您知道整数值不能高于某个大小,则可以创建一个稀疏数组,其中整数值是索引位置,ID是数组单元格的内容。这是最快的,但当然会占用一些空间。