Ruby,使用if / else迭代多值哈希,尝试返回键/值对,在找不到值时失败

问题描述 投票:0回答:3

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

在方法“@@ dictionary.each do | type,list |”中只要将else语句设置为返回nil,初始if语句在构建找到的单词的键/值数组时工作正常。但是,当我尝试将错误/单词对放入数组中以用于未包含在@@字典散列中的单词(即那些属于代码的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
ruby if-statement hash
3个回答
0
投票

它发生的原因是每次遍历所有元素,并且它只有一次或从不。

减少代码可以帮助您了解发生的情况:

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"

0
投票

虽然可能会觉得组织按字典对字典进行分类,但这样做既简化又快得多,因为字典要被展平并且默认设置为'ERROR'标记。

例如:

@@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

0
投票

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

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
© www.soinside.com 2019 - 2024. All rights reserved.