Сортировка массивов в обратном порядке в Rby - PullRequest
0 голосов
/ 06 июля 2018

Я новичок в Ruby и мне нужен кусок кода, который мне объяснят. Массив, который нужно отсортировать, это:

books = ["Charlie and the Chocolate Factory", "War and Peace", "Utopia", 
"A Brief History of Time", "A Wrinkle in Time"]

Блок кода ниже сортирует этот массив books A-Z

books.sort! { |firstBook, secondBook| firstBook <=> secondBook }

Блок кода ниже сортирует этот массив books Z-A

books.sort! { |firstBook, secondBook| secondBook <=> firstBook }

Почему это? Почему первый сортирует A-Z, а второй Z-A? Я вроде понимаю оператор комбинированного сравнения <=>. Возвращает -1, 1 или 0 в зависимости от сравнения. Но как это сортировать вещи? Спасибо!

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

Алгоритм сортировки использует возвращаемое значение из блока, в данном случае это результат оператора сравнения (<=>). Когда возвращается -1, порядок a и b останется прежним (т. Е. a предшествует b. В зависимости от значения алгоритм будет сохранять текущий порядок a и b чтобы узнать, следует ли сортировать a до b (-1), или после (1), или если оба значения эквивалентны (0).

Алгоритм многократно сравнивает соседние пары элементов, пока все элементы не упорядочены.

Давайте добавим некоторые выходные данные, чтобы увидеть, что происходит, когда вы вызываете sort в вашем списке книг. Это даст нам некоторое представление о том, что делает метод сортировки. Я добавил комментарии, чтобы проиллюстрировать, как каждый шаг сортировки изменял массив книг. Обратите внимание, что в этом примере упрощено обсуждение того, как сортировка «меняет» позиции.

> books = ["Charlie and the Chocolate Factory", "War and Peace", "Utopia", "A Brief History of Time", "A Wrinkle in Time"]
> books.sort! do |a, b|
>   result = a <=> b
>   puts %(\n"#{ a }" <=> "#{ b }"  #=> #{ result })  # Print out which elements are being compared and the result
>   result
> end

"Charlie and the Chocolate Factory" <=> "War and Peace"  #=> -1
# ["Charlie and the Chocolate Factory", "War and Peace", "Utopia", "A Brief History of Time", "A Wrinkle in Time"]  *** No change

"War and Peace" <=> "Utopia"  #=> 1
# ["Charlie and the Chocolate Factory", "Utopia", "War and Peace", "A Brief History of Time", "A Wrinkle in Time"]  *** Positions of "Utopia" and "War and Peace" are swapped

"Charlie and the Chocolate Factory" <=> "Utopia"  #=> -1
# ["Charlie and the Chocolate Factory", "Utopia", "War and Peace", "A Brief History of Time", "A Wrinkle in Time"]  *** No change

"War and Peace" <=> "A Brief History of Time"  #=> 1
# ["Charlie and the Chocolate Factory", "Utopia", "A Brief History of Time", "War and Peace", "A Wrinkle in Time"]  *** Positions of "War and Peace" and "A Brief History of Time" are swapped

"Utopia" <=> "A Brief History of Time"  #=> 1
# ["Charlie and the Chocolate Factory", "A Brief History of Time", "Utopia", "War and Peace", "A Wrinkle in Time"]  *** Positions of "Utopia" and "A Brief History of Time" are swapped

"Charlie and the Chocolate Factory" <=> "A Brief History of Time"  #=> 1
# ["A Brief History of Time", "Charlie and the Chocolate Factory", "Utopia", "War and Peace", "A Wrinkle in Time"]  *** Positions of "Charlie and the Chocolate Factory" and "A Brief History of Time" are swapped

"War and Peace" <=> "A Wrinkle in Time"  #=> 1
# ["A Brief History of Time", "Charlie and the Chocolate Factory", "Utopia", "A Wrinkle in Time", "War and Peace"]  *** Positions of "War and Peace" and "A Wrinkle in Time" are swapped

"Utopia" <=> "A Wrinkle in Time"  #=> 1
# ["A Brief History of Time", "Charlie and the Chocolate Factory", "A Wrinkle in Time", "Utopia", "War and Peace"]  *** Positions of "Utopia" and "A Wrinkle in Time" are swapped

"Charlie and the Chocolate Factory" <=> "A Wrinkle in Time"  #=> 1
# ["A Brief History of Time", "A Wrinkle in Time", "Charlie and the Chocolate Factory", "Utopia", "War and Peace"]  *** Positions of "Charlie and the Chocolate Factory" and "A Wrinkle in Time" are swapped

"A Brief History of Time" <=> "A Wrinkle in Time"  #=> -1
# ["A Brief History of Time", "A Wrinkle in Time", "Charlie and the Chocolate Factory", "Utopia", "War and Peace"]  *** No change

# Done! All elements have been sorted, so the algorithm exits.

=> ["A Brief History of Time", "A Wrinkle in Time", "Charlie and the Chocolate Factory", "Utopia", "War and Peace"]

Когда сравнение изменяется с a <=> b на b <=> a, результаты инвертируются, что приводит к сортировке в обратном порядке.

> books = ["Charlie and the Chocolate Factory", "War and Peace", "Utopia", "A Brief History of Time", "A Wrinkle in Time"]
> books.sort! do |a, b|
>   result = b <=> a
>   puts %(\n"#{ b }" <=> "#{ a }"  #=> #{ result })  # Print out which elements are being compared and the result
>   result
> end

"A Wrinkle in Time" <=> "A Brief History of Time"  #=> 1

"Charlie and the Chocolate Factory" <=> "A Brief History of Time"  #=> 1

"Charlie and the Chocolate Factory" <=> "A Wrinkle in Time"  #=> 1

"Utopia" <=> "A Brief History of Time"  #=> 1

"Utopia" <=> "A Wrinkle in Time"  #=> 1

"Utopia" <=> "Charlie and the Chocolate Factory"  #=> 1

"War and Peace" <=> "A Brief History of Time"  #=> 1

"War and Peace" <=> "A Wrinkle in Time"  #=> 1

"War and Peace" <=> "Charlie and the Chocolate Factory"  #=> 1

"War and Peace" <=> "Utopia"  #=> 1
=> ["War and Peace", "Utopia", "Charlie and the Chocolate Factory", "A Wrinkle in Time", "A Brief History of Time"]

См. Также документацию по Array # sort!

0 голосов
/ 06 июля 2018

Оператор сортировки делает то, на что он похож: он сообщает вам, что-то меньше, больше или равно другому объекту в порядке сортировки. Таким образом, ваш первый блок спрашивает «Is firstBook до или после secondBook», а второй блок спрашивает «is secondBook - до или после first book». Как видите, ответ на них противоположный:

  • «A» предшествует до «B» ("A" <=> "B" == -1)
  • «B» следует после «A» ("B" <=> "A" == 1)

Таким образом, если вы измените порядок вопроса, вы получите противоположный ответ, и это означает, что (тип сравнения) алгоритм сортировки даст противоположный результат.

...