开发者

Map objects based on index value

Suppose that i have 2 objects, where each one has a particular slot numbered from 1-5 (unique). Say that object1 has slot = 3 and object2 slot = 5. What is an effective way to create a hash like :

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

I suppose map could be used, but what's the best way ?

EDIT : 5 is just an example, please pretend that 开发者_Go百科you do not know the number of slots.


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

Also:

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


You could just use an array, i.e:

% 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>]

From there you can address object1 in index 3 and object 2 in index 5. Ruby arrays are convenient for this because they'll pad with nils when you add an element beyond the end of the array.


I would use an array since it is more suitable for your reference and has nils by default. The following 1 liner illustrates the usage (using OpenStruct as my object):

> [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>]

If you really do want a hash then I would determine the max slot from the objects themselves like the following:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜