2011-01-21 2 views
3

Руби Array#sort, по умолчанию, сортировать числа, как это, в порядке их значения:Как я могу сортировать числа так, как если бы они были словами?

[11, 12, 13, 112, 113, 124, 125, 127] 

Я хотел бы отсортировать массив чисел, как это, как если бы они были слова быть алфавитный:

[11, 112, 113, 12, 124, 125, 127, 13] 

Как это сделать? (В конечном счете, я хочу сделать это с помощью ключей Hash, поэтому, если вы хотите ответить именно так, все в порядке.) Также есть ли имя для этого типа сортировки?

ответ

7

Вы все crqzy))) У меня есть такое решение:

a.sort_by &:to_s 
+1

Это кратчайшее решение. В Ruby 1.9 вы также можете использовать этот метод для сортировки массива на месте: a.sort_by! (&: To_s) – psyho

+0

@psycho Обратите внимание, что 'sort_by!' - только 1.9.2+ (нет в 1.9.1) – Phrogz

+0

Это существует <333 – Matchu

2

Ну, один из способов - преобразовать все значения в строки, а затем преобразовать их обратно.

a = [11, 12, 13, 112, 113, 124, 125, 127] 
a = a.map(&:to_s).sort.map(&:to_i) 
p a # => [11, 112, 113, 12, 124, 125, 127, 13] 
+0

Ха! Ну, это просто и умно. :) –

+0

Подробный и неэффективный по сравнению с Enumerable # sort_by ... – tokland

+0

@tokland: Мой ответ пришел первым;) 'sort_by', определенно, станет частью моего инструментария в будущем! – Matchu

1

Вы можете pass in a block сортировать, которая принимает два аргумента и возвращает результат вашей собственной пользовательской функции, определенные для сравнения. Пример должен говорить сам за себя, но если у вас возникнут какие-либо вопросы, не стесняйтесь спрашивать.

a = [11, 112, 113, 12, 124, 125, 127, 13] 
new_a = a.sort do |x,y| 
    "%{x}" <=> "%{y}" 
end 
puts new_a 

Примечание: Я подозреваю, что причина, что вы ищете такого рода решения, потому что объекты, которые вы хотите отсортирован не являются Integer s в сердце. Это может быть целесообразным и семантически более приятным для подкласса Integer. Хотя это, очевидно, сделает создание экземпляра более сложным, оно кажется более правильным, по крайней мере для меня.

+1

Мне тоже нравится этот метод, так как его легко расширить в будущем :) +1. Что касается производительности, то, вероятно, лучше всего сделать два преобразования по каждому элементу, чем преобразовывать каждую строку в каждый раз при сравнении. – Matchu

+1

Разница на практике незначительна. Я пересмотрел наши два фрагмента кода, чтобы выполнить более похожие результаты (удалил выходы и добавил '!' К моему вызову метода). В 10k раз я получил 2,7 для моих и 2,8 для ваших. [См. Вывод профилировщика] (http://pastebin.com/raw.php?i=KYe766d9). –

+0

Вы правы, что они не «Integer's's heart»; на самом деле, я действительно использую их как строки, поэтому я не думаю, что в моем случае необходимо подклассировать «Integer». Но я думаю, что это хороший момент для повышения. –