From: Robert Klemme Date: 2004-04-16T18:44:11+09:00 Subject: Re: Performance of Hash.inject "George Ogata" schrieb im Newsbeitrag news:87y8owny24.fsf@optushome.com.au... > "Daniel Sheppard" writes: > > > I was doing some playing with some implementations for Hash#== and ended > > up with some very counterintuitive timings. > > > > I have four equals methods, and I would have expected their performance > > to run (from best to worst): > > > > directInject - stops evaluating == after first bad match, no > > intermediate arrays > > keysInject - as above, but must create keys array > > directCollect - evaluated == for all items all the time, intermediate > > array of results > > keysCollect - as above, but must create keys array. > > Your *Inject methods don't actually quit early; they just stop > evaluating the second expression once val is false. An explicit break > speeds up the quick-exit case considerably. > > > def directInject(hash1, hash2) > > hash1.size == hash2.size && > > hash1.inject(true) { |val, kv| val && hash2[kv[0]] == kv[1] } > hash1.inject(true) { |val, kv| val or break; hash2[kv[0]] == kv[1] } > > end > > def keysInject(hash1, hash2) > > hash1.size == hash2.size && > > hash1.keys.inject(true) { |val, k| val && hash1[k] == hash2[k] } > hash1.keys.inject(true) { |val, k| val or break; hash1[k] == hash2[k] } > > end I would not use inject in this case anyway. I'd prefer returns for fast exit: def directInject(hash1, hash2) return false unless hash1.size == hash2.size hash1.each { |k, v| return false unless hash2[k] == v } true end > Unless you're using a really old ruby, though, Enumerable#all? should > outperform all of the above. You mean def directInject(hash1, hash2) hash1.size == hash2.size and hash1.all? { |k, v| hash2[k] == v } end Yeah, that's even better. robert