From: "Brian Schröder" Date: 2005-08-08T17:16:06+09:00 Subject: Re: String#to_ary and Test::Unit On 08/08/05, David A. Black wrote: > Hi -- > > On Mon, 8 Aug 2005, Trans wrote: > > > In Facets I offer: > > > > class String > > def to_ary > > self.split(//) > > end > > end > > > > This proves useful in adding other methods to Enumerable that can act > > to all enumerables and on strings as character arrays. For instance: > > > > # Generates a hash mapping each unique element to the frequency it > > appears. > > #-- > > # Credit goes to Derek. > > #++ > > def freq > > arr = respond_to?(:to_ary) ? self.to_ary : self.to_a > > probHash = Hash.new > > size = arr.size.to_f > > arr.uniq.each do |i| > > ct = arr.inject(0) do |mem,obj| > > obj.eql?(i) ? (mem+1) : mem > > end > > probHash[i] = ct.to_f/size > > end > > probHash > > end > > This is just a sidenote, but here's a fun way to do that: > > module Enumerable > def freq > arr = to_ary rescue to_a > probs = Hash.new {|h,k| h[k] = arr.find_all {|e| e == k }.size } > arr.uniq.each {|k| probs[k] /= arr.size.to_f } > probs > end > end > > :-) > Another sidenote that removes the need for to_ary completely and is a lot faster: module Enumerable def freq_brian probs = Hash.new(0.0) size = 0.0 each do | e | probs[e] += 1.0 size += 1.0 end probs.keys.each do | e | probs[e] /= size end probs end end user system total real Derek 6.760000 0.790000 7.550000 ( 8.286280) David 4.100000 1.310000 5.410000 ( 5.698582) Brian 0.120000 0.010000 0.130000 ( 0.134124) require 'test/unit' class TC_Frequency < Test::Unit::TestCase ARRAYS = [ [1,2,1,1,1,4,5,6], [1,2,3,4], [], [0,0,0], Array.new(10) { rand(10) }, Array.new(100) { rand(10) }, Array.new(1000) { rand(10) }, Array.new(10000) { rand(10) }, Array.new(10000) { rand(100) } ] def test_brian_david ARRAYS.each do | a | assert_equal(a.freq_david, a.freq_brian, "Brian's is not equal to David's on #{a}") end end def test_brian_derek ARRAYS.each do | a | assert_equal(a.freq_derek, a.freq_brian, "Brian's is not equal to Derek's on #{a}") end end end require 'benchmark' Benchmark.bm do | b | b.report('Derek') do TC_Frequency::ARRAYS.each do | a | a.freq_derek end end b.report('David') do TC_Frequency::ARRAYS.each do | a | a.freq_david end end b.report('Brian') do TC_Frequency::ARRAYS.each do | a | a.freq_brian end end end regards, Brian -- http://ruby.brian-schroeder.de/ Stringed instrument chords: http://chordlist.brian-schroeder.de/