根据索引值映射对象

时间:2011-06-11 22:14:15

标签: ruby-on-rails ruby

假设我有2个对象,每个对象都有一个编号为1-5(唯一)的特定插槽。假设object1有slot = 3而object2 slot = 5。 什么是创建哈希的有效方法:

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

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

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

3 个答案:

答案 0 :(得分:3)

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>}

答案 1 :(得分:1)

你可以使用一个数组,即:

% 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中的对象2. Ruby数组很方便,因为当你在数组末尾添加一个元素时,它们会用nils填充。

答案 2 :(得分:0)

我会使用数组,因为它更适合您的参考,默认情况下为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>}