clean nice way (hash)

S

Stefan Rusterholz

Florian said:
hash.update(hash) { |key, o_val, n_val| Hash['name' => o_val] }

Hash[foo => bar] is a needless method call. foo => bar is already a hash
literal, Hash::[] creates a new hash from that hash (suprised me a bit
tbh, as I don't really see a reason for it to do that), though. But
since that's useless work and method calls weigh heavy in ruby, I'd not
do that.

You can try it if you want:
x = {:a => :b}
Hash[x].equal?(x) # => false

Regards
Stefan
 
F

Florian Aßmann

Ahh, ok, till now I thought {} calls Hash[] but I didn't know what
literals really are...

Thanks
Florian
 
F

Florian Aßmann

Ok, I think GC is the main problem in my setup :D

I tried benchmark and #each behaves much better than #update. #update
produces too much overhead... :(

The source below can kill your memory since I disabled the GC and only
call it manually...

Regards
Florian


require 'benchmark'

Benchmark.bm do |x|
GC.disable

tests =3D [
Proc.new do
hash =3D ('aaaa'..'zzzz').inject Hash.new do |mem, value|
mem[value] =3D value
mem
end
block =3D proc { |key, o_val, n_val| {:name =3D> o_val} }
x.report('Hash#update') { hash.update(hash, &block) }
end ] + [
Proc.new do
hash =3D ('aaaa'..'zzzz').inject Hash.new do |mem, value|
mem[value] =3D value
mem
end
block =3D proc { |key, value| hash[key] =3D {:name =3D> value} }
x.report('Hash#each') { hash.each(&block) }
end
]

12.times do |iteration|
if (iteration % 3).zero?
GC.start
sleep 3
else
tests[ rand(2) ].call
end
end

end
GC.enable
sleep 5
 
R

Robert Klemme

On Jul 16, 2007, at 9:36 AM, Robert Klemme wrote:
2007/7/16, Chris Carter <[email protected]>:
On Jul 16, 2007, at 5:58 AM, hemant wrote:

a.inject({}) {|mem,(key,value)| mem[key] = {'name' => value};
mem }

I would write that as:

a.inject(Hash.new) { |h, (k, v)| h.merge(k => v) }

James Edward Gray II



But that doesn't yield what he wanted... You could do
a.inject(Hash.new){|h,(k,v)| h.merge(k => { 'name' => value})}

Still it's inefficient because of all the small Hashes that are thrown
away immediately. The solution provided by hemant is better although
not as elegant.
If that bothers you, change merge() to merge!().

... which doesn't help because it does not avoid all those one pair
hashes. :)

I did eliminate some Hashes, those created for each iteration inject(),
so I feel it's wrong to say it didn't help. You are right about the
parameter Hashes though.

Those were the ones I referred to originally. And yes, "did not help"
was only partly true. ;-)
I do feel nitpicking something like this is squarely in the domain of
premature optimization though. It's GC's job to lose sleep over the
objects I create, not mine. I don't need to get involved until it looks
like GC is getting behind. Those are my feelings on the matter.

I think I understand your point and as a geneal statement I even do
agree. However, another general statement that I'd add to the mix is
"do not make superfluous work if you can avoid it easily". For me this
is such a case: we just get a slightly more elegant solution by using
#merge because we do not need to mention the Hash to make #inject happy,
but we force the machine to do a lot of extra work (how much remains to
be measured). It's not exactly a comparable case but if I have a tree
where data is stored with a particular order I would not do a full
traversal when searching for a specific element (O(n)); instead I'd use
an algorith that's aware of the tree structure and the ordering (O(log(n))).

Kind regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top