Ezra Zygmuntowicz
7/12/2007 1:21:00 AM
On Jul 11, 2007, at 5:18 PM, Stefan Rusterholz wrote:
>> That said,
>> if you really want to make it O(n+m) (or so, and that's a +
>> instead of a
>> *) you put the arguments list in a hash (which makes the include?
>> call
>> O(1) instead of O(m)). That probably isn't a win until m is more than
>> three
>> (or maybe more, it would require benchmarking to find the magic
>> number),
>> though.
>>
>>> Regards
>>> Stefan
>> --Greg
>
> Since this is a generic method one can't know how it will be used, so
> I'd go for scalability over speed in some anticipated cases. But
> that's
> me.
> You can do it in O(n) (n = keys.length) and I'd even assume that way
> will be faster than the O(m*n) for small n's since the hash is most
> likely longer than the keys-array.
> The O(n) variant simply iterates over the keys and builds up the hash
> from that.
>
> But actually I really just wondered if he was aware about the
> complexity
> of his algorithm :)
>
> Excuse any bad english please, it's a bit late here and english
> isn't my
> first language.
>
> Regards
> Stefan
Yeah I was aware of the complexity. But for what I use it for it's
actually faster then the other way. I mostly use these methods in web
apps to reject or accept keys out of the params hash> Like for
logging the params but blocking any password fields. So the rejected
keys are usually only one or two in number and the whole has usually
has ~10 items in it.
Benchmarking this you will see that block1 is faster then block2 for
the cases I use it for:
class Hash
def block1(*rejected)
self.reject { |k,v| rejected.include?(k) }
end
def block2(*rejected)
hsh = rejected.inject({}){|m,k| m[k] = true; m}
self.reject { |k,v| hsh[k] }
end
end
require 'benchmark'
hash = {:foo => 'foo',
:bar => 'bar',
:baz => 'baz',
:foo1 => 'foo1',
:bar1 => 'bar1',
:baz1 => 'baz1',
:foo2 => 'foo2',
:bar2 => 'bar2',
:baz2 => 'baz2'
}
n = 50000
Benchmark.bm do |x|
puts "block1"
x.report { n.times{ hash.block1(:foo) } }
x.report { n.times{ hash.block1(:foo,:bar) } }
x.report { n.times{ hash.block1(:foo, :bar, :baz) } }
x.report { n.times{ hash.block1(:foo, :bar, :baz,:foo1) } }
x.report { n.times{ hash.block1(:foo, :bar, :baz,:foo1, :bar2) } }
x.report { n.times{ hash.block1
(:foo, :bar, :baz,:foo1, :bar2, :baz2) } }
x.report { n.times{ hash.block1
(:foo, :bar, :baz,:foo1, :bar2, :baz2, :foo3) } }
x.report { n.times{ hash.block1
(:foo, :bar, :baz,:foo1, :bar2, :baz2, :foo3, :bar3) } }
x.report { n.times{ hash.block1
(:foo, :bar, :baz,:foo1, :bar2, :baz2, :foo3, :bar3, :baz3) } }
puts "block2"
x.report { n.times{ hash.block2(:foo) } }
x.report { n.times{ hash.block2(:foo,:bar) } }
x.report { n.times{ hash.block2(:foo, :bar, :baz) } }
x.report { n.times{ hash.block2(:foo, :bar, :baz,:foo1) } }
x.report { n.times{ hash.block2(:foo, :bar, :baz,:foo1, :bar2) } }
x.report { n.times{ hash.block2
(:foo, :bar, :baz,:foo1, :bar2, :baz2) } }
x.report { n.times{ hash.block2
(:foo, :bar, :baz,:foo1, :bar2, :baz2, :foo3) } }
x.report { n.times{ hash.block2
(:foo, :bar, :baz,:foo1, :bar2, :baz2, :foo3, :bar3) } }
x.report { n.times{ hash.block2
(:foo, :bar, :baz,:foo1, :bar2, :baz2, :foo3, :bar3, :baz3) } }
end
Cheers-
-- Ezra