Ruby, перебирающий многозначный хэш с помощью if / else, пытающийся вернуть пары ключ / значение, завершается неудачно, когда значение не найдено - PullRequest
0 голосов
/ 12 февраля 2019

Я пытаюсь отсканировать строку необработанного ввода от пользователя и вернуть предложение, состоящее из массива массивов с парами (TOKEN, WORD).Если слово не является частью лексикона, то оно все равно должно вернуть WORD, но установить для TOKEN токен ошибки.

Внутри метода "@@ dictionary.each do | type, list |"Первоначальный оператор if прекрасно работает при построении массива ключей / значений из найденных слов, если для оператора else установлено значение nil.Однако, когда я пытаюсь поместить пары ошибок / слов в массив для слов, не содержащихся в хеше @@ dictionary (то есть тех, которые попадают в остальную часть кода), я получаю 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

Ответы [ 3 ]

0 голосов
/ 12 февраля 2019

Несмотря на то, что словарь может быть организован по категориям по спискам, это будет и упрощенно, и намного быстрее, если словарь будет сведен к нулю и по умолчанию будет установлен токен «ОШИБКА».

Например:

@@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 голосов
/ 13 февраля 2019

Это сработало для меня.Спасибо Себастьяну Шоллю за идею упрощения словаря.

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
0 голосов
/ 12 февраля 2019

Это происходит из-за того, что каждый из них проходит по всем элементам, и это правда один или никогда.

Это сокращение вашего кода должно помочь вам понять, что происходит:

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"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...