Нахождение N ключей с наибольшим значением в хэше, поддержание порядка - PullRequest
2 голосов
/ 27 февраля 2012

В сценарии Ruby

  • У меня есть хэш, в котором в качестве значений используются предложения, а в качестве значений используются оценки релевантности.
  • Я хочу получить массив, содержащий N наиболее релевантных предложений.(наивысшие баллы).
  • Я хочу сохранить порядок, в котором извлекаются эти предложения.

Дано:

hash = {
  'This is the first sentence.' => 5,
  'This is the second sentence.' => 1,
  'This is the last sentence.' => 6
}

Тогда:

choose_best(hash, 2)

Должен вернуть:

['This is the first sentence.', 'This is the last sentence.']

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

Ответы [ 5 ]

2 голосов
/ 27 февраля 2012
def extract hash, n
  min = hash.values.sort[-n]
  a = []
  i = 0
  hash.each{|k, v| (a.push(k) and i += 1) if i < n and v >= min}
  a
end
1 голос
/ 27 февраля 2012
hash = {
  'This is the first sentence.' => 5,
  'This is the second sentence.' => 1,
  'This is the last sentence.' => 6
}

cutoff_val = hash.values.sort[-2] #cf. sawa
p hash.select{|k,v| v >= cutoff_val } 
# =>{"This is the first sentence."=>5, "This is the last sentence."=>6}
1 голос
/ 27 февраля 2012

Попробуйте следующего монстра:

hash.map(&:reverse).each_with_index
                   .sort_by(&:first).reverse
                   .take(2)
                   .sort_by(&:last)
                   .map { |(_,s),_| s }

Еще один функциональный:

hash.to_a.values_at(*hash.values.each_with_index
                         .sort.reverse
                         .map(&:last)
                         .sort.take(2))
         .map(&:first)

Обратите внимание, что в качестве неупорядоченной структуры данных хеш-таблица не очень подходит для этого варианта использования (хотя порядок помнят в Ruby 1.9). Вместо этого следует использовать массив (код сортировки остается прежним):

sentences = [
  ['This is the first sentence.',  5],
  ['This is the second sentence.', 1],
  ['This is the last sentence.',   6],
]
0 голосов
/ 26 сентября 2014

Начиная с Ruby 2.2.0, Enumerable#max_by принимает необязательный целочисленный аргумент, который заставляет его возвращать массив вместо одного элемента.Поэтому мы можем сделать:

hash = {
  'This is the first sentence.' => 6,
  'This is the second sentence.' => 1,
  'This is the last sentence.' => 5
 }

p hash.max_by(2, &:last).map(&:first).sort_by { |k| hash.keys.index k }
# => ["This is the first sentence.", "This is the last sentence."]

Вызов sort_by в конце гарантирует, что предложения находятся в правильном порядке, как вы и просили.

0 голосов
/ 27 февраля 2012
a = hash.sort_by { |sentence, score| score }.reverse

Массив a теперь содержит пары значений ваших лучших предложений.Вы можете выбрать первые N из них.

hash = {"foo" => 7, "bar" => 2, "blah" => 3 }
a = hash.sort_by { |sentence, score| score }.reverse
=> [["foo", 7], ["blah", 3], ["bar", 2]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...