首页 > 解决方案 > 当我只有值时如何在哈希中返回键?

问题描述

显而易见的答案(至少在我看来)是使用 .key(value) 但是我不断收到错误“未定义的键方法”。我必须返回最高值的第一个实例的键。这是我输入的;

def high(x)
  alphabet = Hash.new(0)
  count = 0
  ("a".."z").each do |char|
    alphabet[char] = count += 1
  end

  words = Hash.new(0)

  x.split(" ").each do |word|
    count_a = 0
    word.each_char do |chars|
      if alphabet.has_key?(chars)
        count_a += alphabet[chars]
      end
    end
    words[word] = count_a
  end

  highest = words.sort_by { |key, value| value }

  (highest[0][1]..highest[-1][1]).each do |val|
    if val == highest[-1][1]
      return highest.key(val)
    else
      return highest[-1][0]
    end
  end
end

我知道这是乱七八糟的代码(我只有几个月的时间学习编码)。我面临的问题具体在以下部分;

highest = words.sort_by { |key, value| value }

  (highest[0][1]..highest[-1][1]).each do |val|
    if val == highest[-1][1]
      return highest.key(val)
    else
      return highest[-1][0]
    end
  end

所以在我写'returnhighest.key(val)'的地方,我希望它返回等于最高'得分'单词的单词,但是它只是给了我未定义的方法错误。任何帮助将不胜感激。

标签: rubysortinghashkey

解决方案


使用可枚举和字符串方法使魔术发生

我很高兴你已经回答了你自己的问题。同时,如果您不关心跟踪所有单词,或者保留每个单词得分的运行列表,那么您可以通过让 Ruby 做更多事情来使这变得更简单、更快、内存更少为您完成的工作,只返回得分最高的项目。

Ruby 有很多内置的方法可以让这样的工作变得更容易,而且它的核心方法通常是高度优化的。这是一个包含七行代码(不包括注释)的解决方案,它利用 Array 继承的Enumerable#zipEnumerable#sumEnumerable#max_by方法来完成大部分繁重的工作。

Hash#merge帮助我们处理一些极端情况,例如复合词中的空格或破折号。然后,在String#charsString#downcase 的帮助下!,这几乎就像 Ruby 为我们做的一样!

在 Ruby 3.0.2 中:

# Map your numerical score to each letter and store in a Hash.
#
# @note We can prepend a value of zero for spaces and other special
#   characters, too!
ALPHA_SCORES = {" " => 0, "-" => 0}.merge (?a..?z).zip(1..26).to_h

# Convert all words to lowercase, and return the highest-scoring word
# and its score as an Array.
def find_highest_scoring_word_in *words
  words.flatten.map do |word|
    word.downcase!
    [word, word.chars.sum { ALPHA_SCORES[_1] }]
  end.max_by(&:last)
end

这种方法提供了很大的灵活性。例如,您可以通过以下所有方式调用它,它会返回正确的结果。

# pass a single Array of String objects
find_highest_scoring_word_in %w[foo bar baz]
#=> ["foo", 36]

# pass two Array of String arguments
find_highest_scoring_word_in %w[foo bar baz], %w[quux wuuble]
#=> ["wuuble", 84]

# pass in three separate String arguments
find_highest_scoring_word_in 'alpha', 'beta', 'gamma'
#=> ["alpha", 38]

# Pass in expressions that evaluate to a String. The first creates 100
# letter a's, and the second 4 z's. Since `z` is worth 26 points, and
# `a` only 1, it's "zzzz" for the win!
find_highest_scoring_word_in 'a' * 100, 'z' * 4
#=> ["zzzz", 104]

推荐阅读