What's the ruby way to sort string with cases in mind

S

Sam Kong

Hi,

I'd like to sort an array of strings case-insensitively.
However, if 2 strings are case-insensitively same, I want capital
letters to come first.

a = %w(a c b A C B)
a.sort_by { |i| i.upcase } # => ["a", "A", "b", "B", "c", "C"]

Actually, I want ["A", "a", "B", "b", "C", "c"] .
I can get the result with the following trick.

a.sort_by {|i| i.upcase + i}

But I think there's a more rubyish way.
How do you do that?

Thanks in advance.

Sam
 
D

Devin Mullins

Sam said:
I'd like to sort an array of strings case-insensitively.
Alternate method (slightly "faster", maybe):
a = %w(a c b A C B)
a.sort {|a,b| a.casecmp b} #=> ["a", "A", "b", "B", "c", "C"]
Actually, I want ["A", "a", "B", "b", "C", "c"] .
I can get the result with the following trick.

a.sort_by {|i| i.upcase + i} Clever.

But I think there's a more rubyish way.
How do you do that?
No clue. Maybe implement your own comparator? {|a,b| dict_order(a,b)}?

Devin
 
M

MonkeeSage

Sam said:
But I think there's a more rubyish way.
How do you do that?

Hi Sam,

I think that's probably the most concise and rubyish way. You can't do
a (simple) sort by ascii ordinal (i[0] in 1.8, or i.ord in 1.9), as
that would give you all the capitals first. And implementing your own
sort routine is not going to be anywhere near as clean as what you've
got. So yeah, imo, go with what you have, it's nice. :)

Regards,
Jordan
 
R

Rimantas Liubertas

And implementing your own
sort routine is not going to be anywhere near as clean as what you've
got.

My best try so far is like that:

a.sort{ |i,j| (i.upcase == j.upcase)? (i<=>j):(i.upcase<=>j.upcase) }

Not elegant, but not too ugly (or is it?). I've got a feeling there
must be a way to simplify this.


Regards,
Rimantas
 
R

Robert Klemme

My best try so far is like that:

a.sort{ |i,j| (i.upcase == j.upcase)? (i<=>j):(i.upcase<=>j.upcase) }

Not elegant, but not too ugly (or is it?). I've got a feeling there
must be a way to simplify this.

a.sort {|i,j| i.upcase == j.upcase ? i <=> j : i.upcase <=> j.upcase}
:)

Maybe a bit more efficient:

a.sort do |i,j|
cmp = i.downcase <=> j.downcase
cmp == 0 ? i <=> j : cmp
end

Cheers

robert
 
M

MonkeeSage

I shouldn't have underestimated my fellow rubyists. I guess
implementing your own sort routine _can_ be *near* as clean. ;)

Regards,
Jordan
 
W

WATANABE Hirofumi

Hi,

Rimantas Liubertas said:
My best try so far is like that:

a.sort{ |i,j| (i.upcase == j.upcase)? (i<=>j):(i.upcase<=>j.upcase) }

Not elegant, but not too ugly (or is it?). I've got a feeling there
must be a way to simplify this.

a.sort{ |i,j| [i.upcase, i] <=> [j.upcase, j] }

a.sort_by{ |i| [i.upcase, i] }
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top