基于索引值的地图对象
问题描述:
假设我有2个对象,其中每个对象都有一个从1-5(唯一)编号的特定插槽。说object1有SLOT = 3和对象2插槽= 5 什么是创建如哈希的有效途径:基于索引值的地图对象
{ 1 => nil, 2 => nil, 3 => object1, 4 => nil, 5 => object2}
我想图可以使用,但什么是最好的方法是什么?
编辑:5只是一个例子,请假装你不知道的时隙数。
答
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>}
答
你可以只使用一个阵列,即:
% 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>}
通过“唯一”你的意思是不同的对象可以*不*(编辑)保持相同的价值? – tokland 2011-06-11 22:32:06
不能保持相同的值:)例如,只有1个对象的插槽编号为3。 – Spyros 2011-06-11 22:33:46