array = [ Fruit.new(:name => "apple", :price => 2),
Fruit.new(:name => "grape", :price => 20),
Fruit.new(:name => "pear", :price => 200) ]
hash = Hash.new
array.each do |obj|
hash.merge!({obj.name => obj.price})
end
hash.inspect # => "{\"grape\"=>20, \"apple\"=>2, \"pear\"=>200}"
The "hash = {} / hash.merge!" thing bugs me... what is the better way?
Mikel
You might like this better:
hash = Hash[*array.map {|e| [e.name, e.price] }.flatten ]
or this:
hash = array.inject({}) {|h, fruit| h[fruit.name] = fruit.price; h }
David
--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS June 9-12 Berlin
ADVANCING WITH RAILS June 16-19 Berlin
INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!
If your general question is something like, "How can I take an array
of objects and turn it into a key/value hash where the key and the
value are based on methods on each object?"
Then you could do something like:
irb> Hash[*array.map{|f|[f.name,f.price]}.flatten]
=> {"grape"=>20, "apple"=>2, "pear"=>200}
If any of the attributes (methods) return Arrays, the flatten will not
produce the result that you want. Also, if the 'name's aren't unique,
the hash will have fewer pairs that the array had entries.
-Rob
Rob Biedenharn http://agileconsultingllc.com
R...@AgileConsultingLLC.com
class Fruit
def to_hash
{ :name => name, :price => price }
end
end
array.each{|fruit| hash.update fruit.to_hash}
a @ http://codeforpeople.com/
--
we can deny everything, except that we have the possibility of being
better. simply reflect on that.
h.h. the 14th dalai lama
Hmm.. put the responsibility back into the class. I guess that
actually makes the most sense.
Thanks David and Rob for your suggestions, totally hadn't considered
those idioms.
Mikel
But this approach has the drawback to create a lot of temporary
instances that are thrown away immediately.
Of course I do not know your use case but if I was building an index
I'd rather insert the object as value instead of a field. Just for
the fun of it:
irb(main):001:0> Fruit = Struct.new :name, :price
=> Fruit
irb(main):002:0> fruits = [Fruit.new("foo",1),Fruit.new("bar",2)]
=> [#<struct Fruit name="foo", price=1>, #<struct Fruit name="bar", price=2>]
irb(main):005:0> indexes = Hash.new {|h,k| h[k]= Hash.new(&h.default_proc)}
=> {}
irb(main):006:0> fruits.each {|f| f.members.each {|m| indexes[m][f[m]]=f}}
=> [#<struct Fruit name="foo", price=1>, #<struct Fruit name="bar", price=2>]
irb(main):008:0> require 'pp'
=> true
irb(main):009:0> pp indexes
{"name"=>
{"foo"=>#<struct Fruit name="foo", price=1>,
"bar"=>#<struct Fruit name="bar", price=2>},
"price"=>
{1=>#<struct Fruit name="foo", price=1>,
2=>#<struct Fruit name="bar", price=2>}}
=> nil
Cheers
robert
--
use.inject do |as, often| as.you_can - without end