Сортировка: сортировка массива на основе нескольких условий в Ruby
У меня есть mulitdimensional массив, например:
[
[name, age, date, gender]
[name, age, date, gender]
[..]
]
Мне интересно, как лучше отсортировать этот массив на основе нескольких условий... Например, как бы я сортировать на основе age сначала, а затем по имени?
Я возился с методом sort
следующим образом:
array.sort { |a,b| [ a[1], a[0] ] <=> [ b[1], b[0] ] }
Кроме того, я не совсем понимаю этот синтаксис, я не получаю ожидаемых результатов. Должен ли я использовать метод sort
? Должен ли я отдельно сравнивать результаты mapping
с массивом?
Ответы
Ответ 1
Вы всегда должны использовать sort_by
для ключевого типа. Это не только намного более читаемо, но и намного эффективнее. Кроме того, я бы предпочел также использовать деструктурирующее связывание для удобочитаемости:
ary.sort_by {|name, age| [age, name] }
Ответ 2
Это должно сделать трюк:
array.sort { |a,b| [ a[1], a[0] ] <=> [ b[1], b[0] ] }
Итак, что это делает? Он использует много идиом Ruby.
- Сначала это блоки, которые похожи на обратные вызовы или анонимные функции/классы на других языках. Метод
sort
Array использует их для сравнения двух элементов на основе возвращаемого значения блока. Вы можете прочитать все о них здесь.
- Следующий оператор
<=>
. Он возвращает -1, если первый аргумент меньше второго, 0, если они равны, и 1, если первый больше второго. Когда вы используете его с массивами, он будет сравнивать массивы по-разному, пока один из них не вернет -1 или 1. Если массивы равны, вы получите 0.
Ответ 3
Как я понимаю, вы хотите сначала заказать по возрасту, а затем, если более чем одна запись имеет тот же возраст, упорядочьте это подмножество по имени.
Это работает для меня
people = [
["bob", 15, "male"],
["alice", 25, "female"],
["bob", 56, "male"],
["dave", 45, "male"],
["alice", 56, "female"],
["adam", 15, "male"]
]
people.sort{|a,b| (a[1] <=> b[1]) == 0 ? (a[0] <=> b[0]) : (a[1] <=> b[1]) }
# The sorted array is
[["adam", 15, "male"],
["bob", 15, "male"],
["alice", 25, "female"],
["dave", 45, "male"],
["alice", 56, "female"],
["bob", 56, "male"]]
Что это такое, сначала сравнивается по возрасту, и если возраст тот же (< = > returs 0), он сравнивает имя.