基于索引值的地图对象

问题描述:

假设我有2个对象,其中每个对象都有一个从1-5(唯一)编号的特定插槽。说object1有SLOT = 3和对象2插槽= 5 什么是创建如哈希的有效途径:基于索引值的地图对象

{ 1 => nil, 2 => nil, 3 => object1, 4 => nil, 5 => object2} 

我想图可以使用,但什么是最好的方法是什么?

编辑:5只是一个例子,请假装你不知道的时隙数。

+0

通过“唯一”你的意思是不同的对象可以*不*(编辑)保持相同的价值? – tokland 2011-06-11 22:32:06

+0

不能保持相同的值:)例如,只有1个对象的插槽编号为3。 – Spyros 2011-06-11 22:33:46

require 'ostruct' 
objects =[OpenStruct.new(:slot => 3), OpenStruct.new(:slot => 5)] 
base = Hash[(1..5).map { |x| [x, nil] }] # also: Hash[(1..5).zip] 
#=> {1=>nil, 2=>nil, 3=>nil, 4=>nil, 5=>nil} 
merged = base.merge(Hash[objects.map(&:slot).zip(objects)]) 
#=> {1=>nil, 2=>nil, 3=>#<OpenStruct slot=3>, 4=>nil, 5=>#<OpenStruct slot=5>} 

另外:

slots = Hash[objects.map(&:slot).zip(objects)] 
#=> {3=>#<OpenStruct slot=3>, 5=>#<OpenStruct slot=5>} 
merged = Hash[(1..5).map { |slot| [slot, slots[slot]] }] 
#=> {1=>nil, 2=>nil, 3=>#<OpenStruct slot=3>, 4=>nil, 5=>#<OpenStruct slot=5>} 
+0

这个看起来很不错,让我测试一下。 – Spyros 2011-06-11 22:34:19

+0

如果超过5个插槽会怎样? – Wes 2011-06-12 04:53:18

+0

@Wes:用插槽数组替换(1..5),无论它是什么。 – tokland 2011-06-12 07:45:38

你可以只使用一个阵列,即:

% irb 
>> object1 = Object.new 
=> #<Object:0x1005ad010> 
>> object2 = Object.new 
=> #<Object:0x1005861e0> 
>> list = Array.new 
=> [] 
>> list[3] = object1 
=> #<Object:0x1005ad010> 
>> list[5] = object2 
=> #<Object:0x1005861e0> 
>> list 
=> [nil, nil, nil, #<Object:0x1005ad010>, nil, #<Object:0x1005861e0>] 

从那里,你可以在指数3解决object1和索引对象5.红宝石阵列对此很方便,因为当你在数组末尾添加一个元素时,它们会用nils填充。

我会使用一个数组,因为它更适合您的参考,默认情况下有nils。下面的1个班轮说明了使用(使用OpenStruct作为我的对象):

> [OpenStruct.new(:slot => 3), OpenStruct.new(:slot => 5)].inject([]) {|s,o| s[o.slot-1] = o; s} 
=> [nil, nil, #<OpenStruct slot=3>, nil, #<OpenStruct slot=5>] 

如果你真的想要一个哈希值,那么我会决定从对象本身的最大插槽如下所示:

> a = [OpenStruct.new(:slot => 3), OpenStruct.new(:slot => 7)] 
=> [#<OpenStruct slot=3>, #<OpenStruct slot=7>] 
> range = 1..a.inject(0) {|s,o| (o.slot>s) ? o.slot : s} 
=> 1..7 
> h = Hash[range.map {|v| [v,nil]}] 
=> {1=>nil, 2=>nil, 3=>nil, 4=>nil, 5=>nil, 6=>nil, 7=>nil} 
> h.merge(Hash[a.map {|v| [v.slot, v]}]) 
=> {1=>nil, 2=>nil, 3=>#<OpenStruct slot=3>, 4=>nil, 5=>nil, 6=>nil, 7=>#<OpenStruct slot=7>}