Попытка понять, как работает функция sort_by в Ruby - PullRequest
3 голосов
/ 23 января 2012

Я прохожу учебник Книга Ублюдков Руби , и мне трудно понять, как работает функция sort_by. Вот упражнение:

Упражнение: сортировка имен по фамилии

Учитывая массив строк, которые представляют имена в форме "FIRSTNAME LASTNAME", используйте sort_by и split, чтобы вернуть массив, отсортированный по фамилиям. Для простоты предположим, что каждое имя состоит только из двух слов, разделенных пробелом (т. Е. Только «Джон Доу», а не «Мэри Джо Доу»).

names = ["John Smith", "Dan Boone", "Jennifer Jane", "Charles Lindy", "Jennifer Eight", "Rob Roy"]

А вот и решение :

names = ["John Smith", "Dan Boone", "Jennifer Jane", "Charles Lindy", "Jennifer Eight", "Rob Roy"]
sorted_names = names.sort_by do |name|
   name.split(" ").reverse.join.upcase
end

puts sorted_names.join('; ')
# output=> Dan Boone; Jennifer Eight; Jennifer Jane; Charles Lindy; Rob Roy; John Smith

Однако, когда я запускаю код

sorted_names = names.sort_by do |name|
  puts name.split(" ").reverse.join.upcase
end

Я получаю вывод:

SMITHJOHN
BOONEDAN
JANEJENNIFER
LINDYCHARLES
EIGHTJENNIFER
ROYROB

, что сильно отличается от вывода puts sorted_names.join('; ')

Я думал, что метод на самом деле манипулирует данными (отсюда name.split(" ").reverse.join.upcase) и затем сохраняет их в новом массиве sorted_names. Но, очевидно, это не так. Итак, мой вопрос, может кто-нибудь объяснить, почему этот метод sort_by действует таким образом. Я относительно новичок в Ruby, и я попытался просмотреть объяснения в Ruby , но не смог его найти. Мне кажется, я не понимаю важную концепцию в Ruby и буду признателен за любую помощь или понимание.

Ответы [ 3 ]

4 голосов
/ 23 января 2012

sort_by вроде как делает это:

a.map {|item| [f(item), item]}.sort.map {|key, item| item}

То есть блок sort_by используется для вычисления ключа сортировки для каждого значения в массиве, а затем эти ключи сортируются, а затемэти ключи возвращаются к исходным значениям.

Итак, вы видите эти ключи, прежде чем они будут использованы для сортировки.За исключением случаев, отмеченных ranksrejoined, put возвращает nil, поэтому, изучив ключи, вы нарушили функцию!

4 голосов
/ 23 января 2012

#sort_by ожидает, что вы вернете значение для сортировки.Тот факт, что у вас есть puts, где должно быть return, заставляет #sort_by возвращать nil для каждого элемента, что предотвращает любую сортировку.

0 голосов
/ 23 января 2012

Не уверен, что это поможет в этом случае, но tap удобно для того, чтобы ковыряться в вещах, не нарушая поток управления:

sorted_names = names.sort_by do |name|
  name.split(" ").reverse.join.upcase.tap { |str| puts str }
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...