Robert Klemme
8/6/2007 11:50:00 AM
2007/8/6, Peña, Botp <botp@delmonte-phil.com>:
> From: Gavin Sinclair [mailto:gsinclair@gmail.com]
> # On Aug 3, 5:58 pm, Peña, Botp <b...@delmonte-phil.com> wrote:
> # > min = list.sort!{|a,b| a.size <=> b.size}.first
> # > break if list.all?{|a| a =~ /^#{min}/} while min.chop!
> # I just realised that the solution I just posted elsewhere in this
> # thread is very very similar to this one.
> # Be careful that using bang methods in chains is sometimes problematic,
> # as they can return nil if nothing changes (sort! doesn't have this
> # problem).
>
> indeed. as long as the array has no nil elements, w're ok w sort!
>
> irb(main):009:0> s="test"
> => "test"
> irb(main):010:0> s.downcase!.downcase!
> NoMethodError: undefined method `downcase!' for nil:NilClass
> from (irb):10
> from :0
> irb(main):011:0> a=[1,1,1]
> => [1, 1, 1]
> irb(main):012:0> a.sort!.sort!
> => [1, 1, 1]
>
> i realized just now that i posted the first code. That should be,
>
> min = list.sort!{|a,b| a.size <=> b.size}.shift # <--shift instead of first
> break if list.all?{|a| a =~ /^#{min}/} while min.chop!
>
> but anyway, after a couple of tests, the sort does not help much, so
>
> min = list.min{|a,b| a.size <=> b.size}
> break if list.all?{|a| a =~ /^#{min}/} while min.chop!
>
> hmm.. Gavin, your until code just gave me a hint. if we reverse logic, we can save the break and make it more readable too.
>
> min = list.min{|a,b| a.size <=> b.size}
> min.chop! until list.all?{|a| a =~ /^#{min}/}
>
> and we can use switch w #any? anytime too :)
>
> min = list.min{|a,b| a.size <=> b.size}
> min.chop! while list.any?{|a| a !~ /^#{min}/}
>
> ruby power, indeed.
All these solutions have the issue that they modify the list which
might or might not be ok. I tend to prefer to view the item list as
read only. So I'd do:
min = list.min{|a,b| a.size <=> b.size}.dup
min.chop! until list.all?{|a| a =~ /^#{min}/}
I have added some interesting benchmarking:
$ ./prefix.rb
user system total real
1000 * list.rx 0.016000 0.000000 0.016000 ( 0.014000)
1000 * list.rx with conversion 0.031000 0.000000 0.031000 ( 0.030000)
1000 * list.one_pass 0.219000 0.000000 0.219000 ( 0.218000)
1000 * list.min 0.328000 0.000000 0.328000 ( 0.337000)
1000 * list.first.dup 0.640000 0.000000 0.640000 ( 0.641000)
1 * large.rx 0.000000 0.000000 0.000000 ( 0.000000)
1 * large.rx with conversion 0.000000 0.000000 0.000000 ( 0.000000)
1 * large.one_pass 25.985000 0.000000 25.985000 ( 26.298000)
1 * large.min 34.953000 0.000000 34.953000 ( 35.098000)
1 * large.first.dup 27.719000 0.000000 27.719000 ( 27.732000)
(see attachment for code)
Kind regards
robert