Array.which_long? ( I coded an extension for Array )


#1

Hi, I’m CFC
I’m new at here.
Nice to meet you:)

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

CFC –


#2

On 4/29/07, Billy H. removed_email_address@domain.invalid wrote:

Hi, I’m CFC
I’m new at here.
Nice to meet you:)

I just coded an extension for Array.
# => 1234

CFC –

How about:
class Array
def longest
self.map {|x| x.to_s }.sort_by {|x| x.size}[-1]
end
end


#3

Hi –

On 4/29/07, Billy H. removed_email_address@domain.invalid wrote:

Hi, I’m CFC
I’m new at here.
Nice to meet you:)

Welcome!

#   ['a', 'ab', 'abc' 1234].which_long?

=> 456
You’re doing too much work – let Ruby do it :slight_smile:

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

David


#4

On 4/29/07, Billy H. removed_email_address@domain.invalid wrote:

# Version 1.0

end

Usage:
puts [1, 23, ‘456’].which_long?
=> 456

CFC –

Hi,

Welcome.

You may be interested in this.
I did not study your code well but I think it is doing something
similar.

p [1, 23, ‘456’].max {|x,y| x.to_s.size <=> y.to_s.size}

Harry


#5

On 4/29/07, Billy H. removed_email_address@domain.invalid wrote:

Hi, I’m CFC
I’m new at here.
Nice to meet you:)
Likewise and welcome to the list :slight_smile:

I just coded an extension for Array.
It will return the longest element of an array.
I hope you posted this for comments, if not just ignore my post, you
will be in good company :wink:

Before I go into the details, one important point, ruby classes are
open which is one of the features of Ruby I like most, but be
careful with this, I use it a lot, but my rule is, never do this in a
library, or a program that might be designed for reuse, exceptions are
of course libraries which just do that, IOW libraries that are
designed and documented as an extensions of a core class.

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

def longest
… forget it skipping to David’s reply


#6

On 4/29/07, David A. Black removed_email_address@domain.invalid wrote:

You’re doing too much work – let Ruby do it :slight_smile:
… 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


#7

Thanks for your reply, I learned more on this thread :stuck_out_tongue:
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 :frowning:

thank you, Chris, David, Harry and Robert :smiley:

CFC –

2007/4/29, David A. Black removed_email_address@domain.invalid:


#8

Hi –

On 4/29/07, Robert D. removed_email_address@domain.invalid wrote:

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 :slight_smile:

David


#9

On 4/29/07, David A. Black removed_email_address@domain.invalid wrote:

end

[‘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 :slight_smile:
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 :slight_smile:
yet

Cheers
Robert


#10

On 4/29/07, David A. Black removed_email_address@domain.invalid wrote:

Hi –

On 4/29/07, Billy H. removed_email_address@domain.invalid wrote:

Thanks for your reply, I learned more on this thread :stuck_out_tongue:
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 :frowning:
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

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


#11

Hi –

On 4/29/07, Billy H. removed_email_address@domain.invalid wrote:

Thanks for your reply, I learned more on this thread :stuck_out_tongue:
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 :frowning:

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


#12

On 4/29/07, James Edward G. II removed_email_address@domain.invalid wrote:

(since there’s no max_by :slight_smile:

Well, not yet:
when I said that above I just dreamt, I had no clue, conclusion =>
YARV fulfills your wildest dreams :wink:

$ 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


#13

On 4/29/07, Billy H. removed_email_address@domain.invalid wrote:

Thanks for your reply, I learned more on this thread :stuck_out_tongue:
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 :frowning:

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


#14

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

end

[‘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 :slight_smile:

Well, not yet:

$ ruby_yarv -e ‘p %w[c bb aaa].max_by { |e| e.to_s.size }’
“aaa”

James Edward G. II


#15

Hi,
Harry, thanks :smiley:


#16

On 29.04.2007 16:11, Chris C. wrote:

def which_long?
long
class Array
def longest
self.map {|x| x.to_s }.sort_by {|x| x.size}[-1]
end
end

Thank you for leaving the #inject solutions to me. :slight_smile:

irb(main):001:0> %w{a ab abc 123 34}.inject{|a,b| a.size > b.size ? a :
b}
=> “123”
irb(main):002:0> %w{a ab abc 123 34}.inject{|a,b| a.size >= b.size ? a :
b}
=> “abc”

Kind regards

robert


#17

On 4/30/07, Robert K. removed_email_address@domain.invalid wrote:

class Array
max }
How about:
class Array
def longest
self.map {|x| x.to_s }.sort_by {|x| x.size}[-1]
end
end

Thank you for leaving the #inject solutions to me. :slight_smile:
Are you kidding I posted an inject solution 19h ago :wink:

But it was to return an array of all longest elements, I guess you can
maybe refine it, it seems clumsy, so I repost it just if you have some
time to play :wink:

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

irb(main):001:0> %w{a ab abc 123 34}.inject{|a,b| a.size > b.size ? a : b}
=> “123”
irb(main):002:0> %w{a ab abc 123 34}.inject{|a,b| a.size >= b.size ? a : b}

You get full credits for this anyway it is really beautiful, can you
stop being so clever ;).

Cheers
Robert


#18

On 30.04.2007 12:39, Robert D. wrote:

self_cpy.each{|item| (max = item.size; long = item) if item.size >

How about:
class Array
def longest
self.map {|x| x.to_s }.sort_by {|x| x.size}[-1]
end
end

Thank you for leaving the #inject solutions to me. :slight_smile:
Are you kidding I posted an inject solution 19h ago :wink:

I am sorry, I did not see it.

          }

end

Hm, I’d probably use case here. Let’s see…

def longest
inject([]) do |lg, e|
case
when lg.empty?, lg.first.size == e.size
lg << e
when lg.first.size < e.size
[e]
else
lg
end
end
end

Alternative, but with higher memory consumption

def longest
lg = Hash.new {|h,k| h[k] = []}
each {|x| lg[x.size] << x}
lg.sort_by {|k,v| k}.last.pop
end

irb(main):001:0> %w{a ab abc 123 34}.inject{|a,b| a.size > b.size ? a
: b}
=> “123”
irb(main):002:0> %w{a ab abc 123 34}.inject{|a,b| a.size >= b.size ? a
: b}

You get full credits for this anyway it is really beautiful, can you
stop being so clever ;).

Since I overlooked your posting I can’t be so clever, can I? :slight_smile:

With #inject it’s really special, it took me a while to pick it up and
now I can’t stop using it. IIRC I even went to the exercise to
implement all methods in Enumerable by using #inject - maybe you can
find it in the archives. :slight_smile:

Kind regards

robert


#19

“Robert D.” removed_email_address@domain.invalid writes:

          }

end

That does seem clumsy. How about:

class Array
def longest
inject([0,[]]) { |(s,l),e|
if e.to_s.size == s then [s,l << e]
elsif e.to_s.size < s then [s,l]
else [e.to_s.size, [e]]
end
}[1]
end
end

Gotta love those destructuring block parameters.


#20

On 30.04.2007 16:11, Robert D. wrote:

On 4/30/07, Robert K. removed_email_address@domain.invalid wrote:

I am sorry, I did not see it.
I was just kidding Robert.

But I did overlook your posting. Honestly. :slight_smile:

          }
   when lg.first.size < e.size

def longest
lg = Hash.new {|h,k| h[k] = []}
each {|x| lg[x.size] << x}
lg.sort_by {|k,v| k}.last.pop
end
good idea but I wanted inject :slight_smile:

That’s an easy transformation (left as exercise for the reader, bonus
points for a one liner). :slight_smile:

Cheers

robert