[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: Array.which_long? ( I coded an extension for Array

dblack

4/29/2007 2:13:00 PM

Hi --

On 4/29/07, Billy Hsu <ruby.maillist@gmail.com> wrote:
> Hi, I'm CFC
> I'm new at here.
> Nice to meet you:)

Welcome!

> I just coded an extension for Array.
> It will return the longest element of an array.
> Source:
>
> class Array
> def which_long?
> # Version 1.0
> # Coded by CFC < zusocfc @ gmail . com >
> # PLEASE DO NOT REMOVE THE COMMENT OF THIS FUNCTION, THANKS A LOT.
> # Usage:
> # ['a', 'ab', 'abc' 1234].which_long?
> # => 1234
> max, long, self_cpy = 0, "", []
> self.size.times{|i| self_cpy << self[i].to_s}
> self_cpy.each{|item| (max = item.size; long = item) if item.size > max }
> long
> end
> end
>
> Usage:
> puts [1, 23, '456'].which_long?
> => 456

You're doing too much work -- let Ruby do it :-)

class Array
def longest
map {|e| e.to_s }.max
end
end


David

--
Upcoming Rails training by Ruby Power and Light:
Four-day Intro to Intermediate
May 8-11, 2007
Edison, NJ
http://www.rubypal.com/event...

9 Answers

Robert Dober

4/29/2007 2:20:00 PM

0

On 4/29/07, David A. Black <dblack@wobblini.net> wrote:
> You're doing too much work -- let Ruby do it :-)
... for sure, but
>
> class Array
> def longest
> map {|e| e.to_s }.max
> end
> end
I think it is not exactly what OP wanted
because %w{x aaaa}.max is "x"
so I will try to comply to his needs
def longest
map{ |e| [e.to_s.size, e.to_s]}.max.first
end

HTH
Robert
>
>
> David
>
> --
> Upcoming Rails training by Ruby Power and Light:
> Four-day Intro to Intermediate
> May 8-11, 2007
> Edison, NJ
> http://www.rubypal.com/event...
>
>


--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw

dblack

4/29/2007 2:38:00 PM

0

Hi --

On 4/29/07, Robert Dober <robert.dober@gmail.com> wrote:
> On 4/29/07, David A. Black <dblack@wobblini.net> wrote:
> > You're doing too much work -- let Ruby do it :-)
> ... for sure, but
> >
> > class Array
> > def longest
> > map {|e| e.to_s }.max
> > end
> > end
> I think it is not exactly what OP wanted
> because %w{x aaaa}.max is "x"
> so I will try to comply to his needs
> def longest
> map{ |e| [e.to_s.size, e.to_s]}.max.first
> end

You're right that I was wrong (because I didn't do the .size thing),
but yours gives you an integer:

['x', 'aaaa'].longest # => 4

I think you'd have to reverse your array. See Harry's code too, which
uses a block with max. You could also do:

sort_by {|e| e.to_s.size }[-1]

(since there's no max_by :-)


David

--
Upcoming Rails training by Ruby Power and Light:
Four-day Intro to Intermediate
May 8-11, 2007
Edison, NJ
http://www.rubypal.com/event...

dblack

4/29/2007 3:04:00 PM

0

Hi --

On 4/29/07, Billy Hsu <ruby.maillist@gmail.com> wrote:
> Thanks for your reply, I learned more on this thread :P
> But I have a question:
> If I have an array contain:
> ary = [1, 12, 234, "456"]
> there has two elements which size is 3, but the longest method just returned
> one of them.
> I can't solve it :(

It depends how you want to break the tie. Here's a way to do it where
a size tie is broken by string comparison, which is ASCII-based. The
nonzero? method will return -1 or 1 if the two string sizes are not
equal. If they are equal, the comparison will evaluate to zero and
nonzero? will be false -- which means the second comparison (the ASCII
one) will be executed.

I've included some tests too.

class Array
def longest
sort do |a,b|
(a.to_s.size <=> b.to_s.size).nonzero? ||
a.to_s <=> b.to_s
end[-1]
end
end

require 'test/unit'

class MaxTest < Test::Unit::TestCase

def test_all_strings
assert_equal("David", %w{ Da David Dav }.longest)
end

def test_all_numbers
assert_equal(34567, [123,12345,200,34567].longest)
end

def test_tie
assert_equal("David", %w{ David Alan Black }.longest)
end

def test_mixed
assert_equal("David", [123, "David", 456].longest)
end

def test_mixed_tie
assert_equal("David", [12345, "David", "Black", 123, 98765].longest)
end
end


David

> 2007/4/29, David A. Black <dblack@wobblini.net>:
> >
> > Hi --
> >
> > On 4/29/07, Robert Dober <robert.dober@gmail.com> wrote:
> > > On 4/29/07, David A. Black <dblack@wobblini.net> wrote:
> > > > You're doing too much work -- let Ruby do it :-)
> > > ... for sure, but
> > > >
> > > > class Array
> > > > def longest
> > > > map {|e| e.to_s }.max
> > > > end
> > > > end
> > > I think it is not exactly what OP wanted
> > > because %w{x aaaa}.max is "x"
> > > so I will try to comply to his needs
> > > def longest
> > > map{ |e| [e.to_s.size, e.to_s]}.max.first
> > > end
> >
> > You're right that I was wrong (because I didn't do the .size thing),
> > but yours gives you an integer:
> >
> > ['x', 'aaaa'].longest # => 4
> >
> > I think you'd have to reverse your array. See Harry's code too, which
> > uses a block with max. You could also do:
> >
> > sort_by {|e| e.to_s.size }[-1]
> >
> > (since there's no max_by :-)
> >
> >
> > David
> >
> > --
> > Upcoming Rails training by Ruby Power and Light:
> > Four-day Intro to Intermediate
> > May 8-11, 2007
> > Edison, NJ
> > http://www.rubypal.com/event...
> >
> >
>
>
> --
> Taiwan Ruby Users Group:
> http://www.ru...
> http://www.ru...phpbb
>


--
Upcoming Rails training by Ruby Power and Light:
Four-day Intro to Intermediate
May 8-11, 2007
Edison, NJ
http://www.rubypal.com/event...

Robert Dober

4/29/2007 3:07:00 PM

0

On 4/29/07, David A. Black <dblack@wobblini.net> wrote:
> Hi --
>
> On 4/29/07, Robert Dober <robert.dober@gmail.com> wrote:
> > On 4/29/07, David A. Black <dblack@wobblini.net> wrote:
> > > You're doing too much work -- let Ruby do it :-)
> > ... for sure, but
> > >
> > > class Array
> > > def longest
> > > map {|e| e.to_s }.max
> > > end
> > > end
> > I think it is not exactly what OP wanted
> > because %w{x aaaa}.max is "x"
> > so I will try to comply to his needs
> > def longest
> > map{ |e| [e.to_s.size, e.to_s]}.max.first
> > end
>
> You're right that I was wrong (because I didn't do the .size thing),
> but yours gives you an integer:
>
> ['x', 'aaaa'].longest # => 4
>
> I think you'd have to reverse your array.
Together we might get there ;), maybe just applying #last instead of #first.
See Harry's code too, which
> uses a block with max.
Which is great, I admit that is the nicest solution, learned something again :)
You could also do:
>
> sort_by {|e| e.to_s.size }[-1]
That's nice too, (personally I prefer #last to [-1])
>
> (since there's no max_by :-)
yet
>
>
Cheers
Robert
>


--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw

Robert Dober

4/29/2007 3:21:00 PM

0

On 4/29/07, David A. Black <dblack@wobblini.net> wrote:
> Hi --
>
> On 4/29/07, Billy Hsu <ruby.maillist@gmail.com> wrote:
> > Thanks for your reply, I learned more on this thread :P
> > But I have a question:
> > If I have an array contain:
> > ary = [1, 12, 234, "456"]
> > there has two elements which size is 3, but the longest method just returned
> > one of them.
> > I can't solve it :(
Alternatively I can use my erroneous code from above to give you all
longest elements
def longest
longest_size = map{ |e| [e.to_s.size, e.to_s]}.max.first
reject{ |x| x.size < longest}
end

this is slow though, maybe the following is preferable - but not so readable -
def longest
inject([]){ |s, e|
if s.empty? || s.first.size < e.to_s.size then [e]
elsif s.first.size == e.to_s.size then s << e
else s
end
}
end

> <tie breaking solutions snipped>
Robert
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw

James Gray

4/29/2007 3:25:00 PM

0

On Apr 29, 2007, at 9:38 AM, David A. Black wrote:

> Hi --
>
> On 4/29/07, Robert Dober <robert.dober@gmail.com> wrote:
>> On 4/29/07, David A. Black <dblack@wobblini.net> wrote:
>> > You're doing too much work -- let Ruby do it :-)
>> ... for sure, but
>> >
>> > class Array
>> > def longest
>> > map {|e| e.to_s }.max
>> > end
>> > end
>> I think it is not exactly what OP wanted
>> because %w{x aaaa}.max is "x"
>> so I will try to comply to his needs
>> def longest
>> map{ |e| [e.to_s.size, e.to_s]}.max.first
>> end
>
> You're right that I was wrong (because I didn't do the .size thing),
> but yours gives you an integer:
>
> ['x', 'aaaa'].longest # => 4
>
> I think you'd have to reverse your array. See Harry's code too, which
> uses a block with max. You could also do:
>
> sort_by {|e| e.to_s.size }[-1]
>
> (since there's no max_by :-)

Well, not yet:

$ ruby_yarv -e 'p %w[c bb aaa].max_by { |e| e.to_s.size }'
"aaa"

James Edward Gray II


Robert Dober

4/29/2007 3:38:00 PM

0

On 4/29/07, James Edward Gray II <james@grayproductions.net> wrote:

> > (since there's no max_by :-)
>
> Well, not yet:
when I said that above I just dreamt, I had no clue, conclusion =>
YARV fulfills your wildest dreams ;)
>
> $ ruby_yarv -e 'p %w[c bb aaa].max_by { |e| e.to_s.size }'
> "aaa"
I guess there will be a #min_by too,
how does it break ties? Well I ask too much I gotta go the last snapshot...

BTW instead of
a[ rand(a.size) ]
we can write
a.max_by{ rand }
now; LOL!

Robert
--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw

Harry Kakueki

4/29/2007 10:14:00 PM

0

On 4/29/07, Billy Hsu <ruby.maillist@gmail.com> wrote:
> Thanks for your reply, I learned more on this thread :P
> But I have a question:
> If I have an array contain:
> ary = [1, 12, 234, "456"]
> there has two elements which size is 3, but the longest method just returned
> one of them.
> I can't solve it :(
>

Is this what you are looking for?
Do you want all longest elements?

big = [1, 12, 234,45,978, "456"].max {|x,y| x.to_s.size <=> y.to_s.size}
p [1, 12, 234,45,978, "456"].select {|r| r.to_s.size == big.to_s.size}

Harry

--
http://www.kakueki.com/ruby...
A Look into Japanese Ruby List in English

Rick DeNatale

5/3/2007 2:28:00 PM

0

On 4/29/07, James Edward Gray II <james@grayproductions.net> wrote:
> On Apr 29, 2007, at 9:38 AM, David A. Black wrote:

> > I think you'd have to reverse your array. See Harry's code too, which
> > uses a block with max. You could also do:
> >
> > sort_by {|e| e.to_s.size }[-1]
> >
> > (since there's no max_by :-)
>
> Well, not yet:
>
> $ ruby_yarv -e 'p %w[c bb aaa].max_by { |e| e.to_s.size }'
> "aaa"

Actually Array#max already takes a block, and the Rdoc actually uses
almost this very use case to document it:

$ qri Array#max
--------------------------------------------------------- Enumerable#max
enum.max => obj
enum.max {|a,b| block } => obj
------------------------------------------------------------------------
Returns the object in enum with the maximum value. The first form
assumes all objects implement Comparable; the second uses the
block to return a <=> b.

a = %w(albatross dog horse)
a.max #=> "horse"
a.max {|a,b| a.length <=> b.length } #=> "albatross"


Harry gave a solution along these lines early on in the thread, but no
one seems to have noticed.

The observation that 1.9 is adding max_by is interesting, but it's
more a matter of syntactic sugar than the difference between sort and
sort_by since max only needs to evaluate the block once for each
element.

Now max_by is nicer since the block just needs to return the
comparison value rather than a comparison result.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denh...