From: Jim Weirich Date: 2005-05-22T13:37:59+09:00 Subject: Re: join not in Enumerable On Saturday 21 May 2005 10:05 pm, David A. Black wrote: > Hi -- > > On Sun, 22 May 2005, Logan Capaldo wrote: > > Just a few minutes ago I was playing with irb as I am wont to do, and > > typed this: > > > > ('a'..'z').join(' ') > > > > Lo and behold it protested at me with a NoMethodError. I said to my > > self, self there is no reason that has to be Array only functionality. > > Why isn't it in Enumerable? So I said: > > > > module Enumerable > > def join(sep = '') > > inject do |a, b| > > "#{a}#{sep}#{b}" > > end > > end > > end > > > > And then I said ('a'..'z').join(' ') and got: > > => "a b c d e f g h i j k l m n o p q r s t u v w x y z" > > > > #inject has to be the most dangerously effective method ever. But I > > digress: > > You can speed it up a lot if you do this: [... elided version using to_a ...] The reason the non-to_a version is slow is because it creates a series of increasingly larger strings. A faster version (without resorting to to_a) would build up a single string gradually. Here is another version: def join(sep='') inject(nil) { |a, b| a ? (a << sep << b.to_s) : "#{b}" } end Here are the timings I got ... user system total real to_a: 0.580000 0.000000 0.580000 ( 0.583975) inject slow: 10.520000 0.210000 10.730000 ( 11.998484) inject fast: 0.590000 0.020000 0.610000 ( 0.651972) -- -- Jim Weirich jim@weirichhouse.org http://onestepback.org ----------------------------------------------------------------- "Beware of bugs in the above code; I have only proved it correct, not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)