【问题标题】:Ruby, iterating over a multi-value Hash using if/else, trying to return key/value pairs, fails when value is not foundRuby,使用 if/else 迭代多值哈希,尝试返回键/值对,当找不到值时失败
【发布时间】:2019-02-12 14:30:37
【问题描述】:

我正在尝试扫描来自用户的原始输入字符串并返回一个句子,该句子由具有 (TOKEN, WORD) 配对的数组组成。如果单词不是词典的一部分,那么它仍应返回 WORD 但将 TOKEN 设置为错误标记。

在方法“@@dictionary.each 中做 |type, list|”只要将 else 语句设置为返回 nil,初始 if 语句就可以很好地构建找到的单词的键/值数组。但是,当我尝试将错误/单词对放入数组中以查找未包含在 @@dictionary 哈希中的单词(即那些属于代码的 else 部分的单词)时,我在数组中为每个单词收到 5 个单独的对用户输入的,对于输入的每个单词的每个键的每次迭代都有一个。

有没有人知道如何只将一个错误/值对返回到数组中,而不是为每个单词的五次迭代中的每一次返回一个?

class Lexicon

@@dictionary = {
  'direction' => ['north', 'south', 'east', 'west', 'down', 'up', 'left', 'right', 'back'],
  'verbs' => ['go', 'stop', 'kill', 'eat'],
  'stop words' => ['the', 'in', 'of', 'on', 'at', 'it'],
  'nouns' => ['door', 'bear', 'princess', 'cabinet'],
  'numbers' => [0..9]
}

stuff = $stdin.gets.chomp
@@words = stuff.split(' ')

    def self.scan
        result = []

        @@words.each do |text_element|
            categorized = []

            @@dictionary.each do |type, list|
                if
                    list.include?(text_element.downcase)
                    categorized = [type, text_element]
                    result.push(categorized)
                else
                    nil
                    #categorized = ["ERROR", text_element]
                    #result.push(categorized)
                end
            end
        end
        print result
    end

Lexicon.scan

end

【问题讨论】:

  • 您能否用输入示例和您期望的输出来更新您的问题?
  • 输入:公主看到了一只熊。当 else 为 nil 时,输出 [["stop words", "The"], ["nouns", "princess"], ["nouns", "bear"]] 当 else 被分类时 = ["ERROR", text_element] ; result.push(categorized), 输出 [["ERROR", "the"], ["ERROR", "the"], ["stop words", "the"], ["ERROR", "the"], ["ERROR", "the"], ["ERROR", "princess"], ["ERROR", "princess"], ["ERROR", "princess"], ["nouns", "princess"], [“错误”,“公主”],[“错误”,“锯”],[“错误”,“锯”],[“错误”,“锯”],[“错误”,“锯”], ["ERROR", "saw"], ["ERROR", "a"], ["ERROR", "a"], ["ERROR", "a"], ["ERROR", "a"],等等……

标签: ruby if-statement hash


【解决方案1】:

发生这种情况是因为 each 迭代了所有元素,并且它是真的一次或永远不会。

您的代码减少应该有助于您了解发生了什么:

dictionary = {
  'direction' => ['north', 'south'],
  'verbs' => ['go', 'stop', 'kill', 'eat'],
  'whathever' => ['blah']
}

text = 'go'
dictionary.each do |type, list|
  if p list.include?(text) # added p
    then
      p text
    else
      p 'error'
  end
end

返回:

# false
# "error"
# true
# "go"
# false
# "error"

您需要一种不同的方法,例如:

text = 'nothing'
result = dictionary.find { |_, v| v.include? text }
result ? [result.keys, text] : "Error"

【讨论】:

    【解决方案2】:

    虽然将字典按列表分类可能让人觉得很有条理,但如果字典被展平并默认设置为“错误”标记,这将既简化又快得多。

    例如:

    @@dictionary = {
      'direction' => ['north', 'south', 'east', 'west', 'down', 'up', 'left', 'right', 'back'],
      'verbs' => ['go', 'stop', 'kill', 'eat'],
      ...
    

    变成这样:

    @@dictionary = {
      'north' => 'direction',
      'south' => 'direction',
      ...
      'go' => 'verbs',
      'stop' => 'verbs',
      ...
    }
    
    @@dictionary.default = 'ERROR'
    

    这样,您的查找就变成了线性的,并且没有不必要的布尔逻辑,就像这样。

    def scan
      result = stuff.split(' ').map do |word|
        [@@dictionary[word.downcase], word]
      end
    
      print result
    end
    

    【讨论】:

      【解决方案3】:

      这对我有用。感谢 Sebastian Scholl 提出的简化字典的想法。

      class Lexicon
      
      @@dictionary = {
        'direction' => ['north', 'south', 'east', 'west', 'down', 'up', 'left', 'right', 'back'],
        'verbs' => ['go', 'stop', 'kill', 'eat'],
        'stop words' => ['the', 'in', 'of', 'on', 'at', 'it'],
        'nouns' => ['door', 'bear', 'princess', 'cabinet'],
        'numbers' => [0..9]
      }
      
      stuff = $stdin.gets.chomp
      @@words = stuff.downcase.split(' ')
      
          def self.scan
              result = []
              values = []
              @@dictionary.each do |key, value|
                  values << value
              end
      
              value_list = values.flatten.uniq
      
              @@words.each do |text_element|
                  if value_list.include?(text_element)
                      @@dictionary.each do |key, value|
                          if value.include?(text_element)
                              categorized = [key, text_element]
                              result.push(categorized)
                          else
                              nil
                          end
                      end
                  else
                      result.push(["Error, #{text_element}"])
                  end
              end
              print result
          end
      Lexicon.scan
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-11
        • 2016-04-23
        • 1970-01-01
        • 1970-01-01
        • 2011-06-30
        • 1970-01-01
        • 2018-08-22
        • 1970-01-01
        相关资源
        最近更新 更多