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

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

Sam Kong wrote:

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

Sam Kong wrote:

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

Regards,
Jordan

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

···

--
http://rimantas.com/

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

Maybe a bit more efficient:

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

Cheers

  robert

···

On 20.09.2006 09:19, Rimantas Liubertas wrote:

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.

Hi,

"Rimantas Liubertas" <rimantas@gmail.com> writes:

> 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.

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

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

···

--
eban

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

Regards,
Jordan

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

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

Great! I guess we have the winner :slight_smile:

Regards,
Rimantas

···

--
http://rimantas.com/

Hi,

WATANABE Hirofumi wrote:

Hi,

"Rimantas Liubertas" <rimantas@gmail.com> writes:

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

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

Wow!
This is what I was looking for.
Why couldn't I think of this?

Thank you very much.

Sam

Nice one, Hirofumi-shi! :slight_smile:

Regards,
Jordan

+1

  robert

···

On 20.09.2006 10:56, Rimantas Liubertas wrote:

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

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

Great! I guess we have the winner :slight_smile: