почему array.sort{|x,y| y ‹=› x} отсортировать массив в порядке убывания в Ruby?

Недавно я наткнулся на фрагмент кода, который использовал

array.sort{|x,y| y <=> x}

для сортировки массива целых чисел в порядке убывания. Я посмотрел оператор ‹=> и понял, что он возвращает три разных значения: -1, 0 или 1, в зависимости от того, меньше ли одно значение, больше или равно другому другому значению.

Но я не могу объяснить, почему приведенный выше код сортирует массив в порядке убывания, но знаю, что это определенно происходит благодаря IRB. Что тут происходит? Кто-нибудь может мне это объяснить?


person wendybeth    schedule 11.07.2014    source источник


Ответы (3)


По тем же причинам, что и это:

array.sort{|x,y| x <=> y}

Сортирует по возрастанию.


Возьмем, к примеру, эту программу:

[1,5,2,4,3].sort do |x,y|
  puts "---"
  puts x
  puts y
  puts x <=> y
  x <=> y
end

Он выведет два сравниваемых числа, а затем результат <=> во время сортировки. Выводит это:

---
1
2
-1 # 1 is less than 2
---
2
3
-1 # 2 is less than 3
---
5
2
1 # 5 is greater than 1
---
4
2
1 # 4 is greater than 2
---
5
4
1 # 5 is greater than 4
---
4
3
1 # 4 is greater than 3

Если вы измените порядок x <=> y на y <=> x, вы получите противоположный результат.

person Ryan Bigg    schedule 11.07.2014
comment
Спасибо. Я понял, что он будет сортировать его в порядке возрастания, если x и y поменялись местами. Я просто не понял, откуда появился ‹=›. Таким образом, он в основном перебирает каждое значение в массиве, а затем отображает его в новый массив, например... перетасовывая колоду карт, с неупорядоченными картами под вашим пальцем , и с каждой картой, которую вы берете из неупорядоченной стопки, проверяя, должна ли она идти впереди или позади карты, на которую вы смотрите, в отсортированной стопке? - person wendybeth; 11.07.2014
comment
Это не то, что он делает - этот алгоритм сортировки звучит как сортировка вставками и медленнее, чем алгоритм быстрой сортировки, используемый ruby. - person Frederick Cheung; 11.07.2014

Потому что вы сделали y ‹=> x, а не x ‹=> y. Порядок аргументов важен.

person Tyler Eaves    schedule 11.07.2014

Я решил дать ответ, который, я надеюсь, будет понятен большинству новичков в Ruby.

Array#sort сравнивает каждую пару элементов в массиве. Для каждой пары элементов x,y блок sort возвращает -1, если x предшествует y в сортировке, 1, если y предшествует x, и 0, если один из них может предшествовать другому. Если блок не задан, sort использует блок:

{ |x,y| x <=> y }

Если, например, x и y являются строками, метод String#‹=> можно определить следующим образом:

class String
  def <=>(other)
    case
    when self < other then -1
    when self > other then  1
    else 0
    end
  end
end

Аналогично, Array#‹= > вызывается, если x и y являются массивами и т. д. Для Fixnums, Bignums и Floats (все из классов, происходящих от Numeric), метод Numeric#‹=>, поэтому сортируемый массив может содержать смесь этих трех типов данных.

Если блок sort:

{ |x,y| y <=> x }

блок возвращает показанные здесь значения (со значениями по умолчанию x <=> y, показанными для сравнения):

введите здесь описание изображения

Теперь предположим, что мы хотим отсортировать массив [2,3,1,2]. Для значения по умолчанию sort блок сортировки с x <=> y возвращает показанные здесь значения:

введите здесь описание изображения

что заставляет sort возвращать [1,2,2,3]. Если блок сортировки

{ |x,y| y <=> x }

блок сортировки возвращает следующие значения:

введите здесь описание изображения

заставляя sort возвращать [3,2,2,1].

person Cary Swoveland    schedule 11.07.2014