Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Ruby (http://www.velocityreviews.com/forums/f66-ruby.html)
-   -   Cleaner way to do this? (http://www.velocityreviews.com/forums/t817770-cleaner-way-to-do-this.html)

Harry Ohlsen 11-05-2004 12:18 AM

Cleaner way to do this?
 
Hi,

One of my colleagues asked me last night how he could do some processing
on every object of an array, with different processing for the first
item ... but without generating an intermediate variable.

An example would be doing the equivalent of

puts a.join(", ")

without having a temporary string created. The temporary string isn't
an issue normally, but imagine if the array is huge.

Trying to make it reasonably flexible, I came up with the following, but
I figure there's probably some cleaner way to do it.

Maybe there's a method I don't know about that allows for this kind of
thing. Any suggestions?

Pardon the method name ... it's only a model :-)

class Array
def first_and_rest(first_time)
first_time.call self[0]

(1 .. self.length - 1).each do |i|
yield self[i]
end
end
end

a = [1, 2, 3, 4, 5]

File.open("test.txt", "w") do |out|
a.first_and_rest(proc {|x| out.print x}) do |x|
out.print ", #{x}"
end

out.puts
end


************************************************** **********************

If you have received this e-mail in error, please delete it and notify the sender as soon as possible. The contents of this e-mail may be confidential and the unauthorized use, copying, or dissemination of it and any attachments to it, is prohibited.

Internet communications are not secure and Hyperion does not, therefore, accept legal responsibility for the contents of this message nor for any damage caused by viruses. The views expressed here do not necessarily represent those of Hyperion.

For more information about Hyperion, please visit our Web site at www.hyperion.com






Wayne Vucenic 11-05-2004 01:12 AM

Re: Cleaner way to do this?
 
How about

[1, 2, 3, 4, 5].each_with_index do |x, i|
if i == 0
print x
else
print ", ",x
end
end

Wayne

-----
No Bugs Software
"Ruby and C++ Contract Programming in Silicon Valley"



Ara.T.Howard@noaa.gov 11-05-2004 02:18 AM

Re: Cleaner way to do this?
 
On Fri, 5 Nov 2004, Harry Ohlsen wrote:

> Hi,
>
> One of my colleagues asked me last night how he could do some processing
> on every object of an array, with different processing for the first
> item ... but without generating an intermediate variable.
>
> An example would be doing the equivalent of
>
> puts a.join(", ")
>
> without having a temporary string created. The temporary string isn't
> an issue normally, but imagine if the array is huge.
>
> Trying to make it reasonably flexible, I came up with the following, but
> I figure there's probably some cleaner way to do it.
>
> Maybe there's a method I don't know about that allows for this kind of
> thing. Any suggestions?
>
> Pardon the method name ... it's only a model :-)
>
> class Array
> def first_and_rest(first_time)
> first_time.call self[0]
>
> (1 .. self.length - 1).each do |i|
> yield self[i]
> end
> end
> end
>
> a = [1, 2, 3, 4, 5]
>
> File.open("test.txt", "w") do |out|
> a.first_and_rest(proc {|x| out.print x}) do |x|
> out.print ", #{x}"
> end
>
> out.puts
> end


hard to profile with IO involved but:

harp:~ > ruby a.rb
1048576
-------------------------------------------------------------------------------
first_and_rest
-------------------------------------------------------------------------------
7.89007091522217
549755289600
-------------------------------------------------------------------------------
ruby objects are copy on write references - no copy is made here!
-------------------------------------------------------------------------------
6.67814898490906
549755289600
-------------------------------------------------------------------------------
is testing __really__ that slow?
-------------------------------------------------------------------------------
13.0074229240417
549755289600

harp:~ > cat a.rb
def time label
puts('-' * 79)
puts label
puts('-' * 79)
a = Time::now
yield
b = Time::now
puts(b.to_f - a.to_f)
end

class Array
def first_and_rest(first_time)
first_time.call self[0]
(1 .. self.length - 1).each do |i|
yield self[i]
end
end
end

huge = (0...(2 ** 20)).to_a
p huge.size


sum = 0
time('first_and_rest') do
huge.first_and_rest(proc {|x| sum += x}) do |x|
sum += x
end
end
p sum

sum = 0
time('ruby objects are copy on write references - no copy is made here!') do
first = huge.first
sum += first
huge.last(huge.size - 1).each{|x| sum += x}
end
p sum

sum = 0
time('is testing __really__ that slow?') do
huge.each_with_index do |x, i|
sum += (i == 0 ? (x * 2) : x)
end
end
p sum


so testing is slow, however i couldn't really tell the difference until a
million entries or so. in any case i think your friend isn't clear on the
meaning of 'created' - unless you modify the first element no copy is made -
you just get a reference which costs basically nothing. to prove it:

harp:~ > ruby b.rb
1048576
-------------------------------------------------------------------------------
it's plenty fast to take references
-------------------------------------------------------------------------------
3.60012054443359e-05
-------------------------------------------------------------------------------
but slow(er) if you actually copy on write
-------------------------------------------------------------------------------
36.049026966095


harp:~ > cat b.rb
def time label
puts('-' * 79)
puts label
puts('-' * 79)
a = Time::now
yield
b = Time::now
puts(b.to_f - a.to_f)
end

huge = '_' * (2 ** 20)
p huge.size


time("it's plenty fast to take references"){ 42.times{ s = huge } }
time("but slow(er) if you actually copy on write"){ 42.times{ (s = huge).gsub(%r/./,'!') } }


IMHO the copy on write semantics of ruby assignment is one of it's nicest
features - it's a lot easier to shoot your self in the foot with memory
allocation in perl.


kind regards.

-a
--
================================================== =============================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| When you do something, you should burn yourself completely, like a good
| bonfire, leaving no trace of yourself. --Shunryu Suzuki
================================================== =============================


All times are GMT. The time now is 11:42 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.