Сортування за зменшенням за значенням Хешу в Ruby


76

Мій хеш вводу: h = { "a" => 20, "b" => 30, "c" => 10 }

Сортування за зростанням: h.sort {|a,b| a[1]<=>b[1]} #=> [["c", 10], ["a", 20], ["b", 30]]

Але мені потрібно [["b", 30], ["a", 20], ["c", 10]]

Як ми можемо змусити це працювати навпаки, що це <=>означає?

Відповіді:


188

Ви можете зробити його чистішим, зрозумілішим і швидшим, відразу! Подобається це:

h.sort_by {|k,v| v}.reverse

Я порівняв терміни на 3000 ітераціях сортування хешу з 1000 елементів із випадковими значеннями і отримав такі часи:

h.sort {|x,y| -(x[1]<=>y[1])} -- 16.7s
h.sort {|x,y| y[1] <=> x[1]} -- 12.3s
h.sort_by {|k,v| -v} -- 5.9s
h.sort_by {|k,v| v}.reverse -- 3.7

3
Візуально це чистіше, але це спричиняє додатковий обхід колекції, щоб повернути її назад.
Олов'янець

@glennmcdonald, скажіть, будь ласка, як можна розрахувати час кожного дзвінка в рубіні?
боддхісаттва

1
Я дізнався, як розрахувати час, коли відбувається кожен дзвінок. Ось зразок посилання: - ruby-doc.org/core-1.9.3/Enumerable.html#method-i-sort
boddhisattva

Що про h.sort_by(&:last).reverse? Був раз на це?
Круз Нуньєс

Яка версія Ruby?
danielrice кодує

12
h.sort {|a,b| b[1]<=>a[1]}

7
Я підтримав цей коментар не тому, що відповідь неправильна, а тому, що ви не пояснюєте, чому це правильна відповідь. Той, хто запитує, навіть конкретно запитав, що означає "<=>" - отже, він (-і), очевидно, після якогось пояснення, як це все працює. Це гарна ідея допомогти цим шляхом :)
Тарін Іст

PS: докладніше див. Політику перегляду стека щодо переповнення мета: meta.stackexchange.com/questions/74194/…
Taryn East

10

<=>порівнює два операнди, повертаючи -1, якщо перший нижчий, 0, якщо вони рівні, і 1, якщо перший вище. Це означає, що ви можете просто -(a[1]<=>b[1])змінити порядок.


1
Я завжди волію бачити, як це пишеться з місцями "a" та "b", а не заперечуючи результат. Помінявши їх місцями, мені залишається лише поглянути на їхній наказ, щоб побачити, що вони зворотні, щоб знати, що це змінилося. Коли значення <=>заперечується, я все одно маю поглянути на фактичне порівняння, щоб знати, що відбувається. Це незначний момент, але те, про що я знаю, бо я відчуваю, що мій мозок повинен зробити другу перевірку після того, як зробив "Що !?"
Олов'янець

1
@Greg: Я точно розумію, чому ти віддав би перевагу іншому шляху. Я протилежний: для моїх очей, що сканують, це b[1]<=>a[1]схоже на привіт, a[1]<=>b[1]і я відчуваю необхідність зупинитися і перевірити, тоді як заперечення відразу робить очевидним, що ми робимо зворотне сортування.
Чак,

Я теж розумію вашу думку. У будь-якому випадку це все одно вимагає ретельного вивчення порівняних значень. Можливо, нам потрібен інший оператор - >=<для зворотного порядку? Ні, це було б так само погано. Це вся конструкція, але я віддаю перевагу <=>більш детальному підходу, де нам доводиться називати деякі імена методів.
Олов'янець

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.