Как напечатать все пары ключ-значение в Ruby hash?

#ruby #hash

#ruby #хэш

Вопрос:

Приношу свои извинения за потенциально глупый вопрос, я абсолютный новичок в Ruby и коде в целом.

Я настроил хэш с некоторыми предопределенными значениями. Я хочу запросить у пользователя ввод, если этот ввод соответствует существующему ключу, я хочу, чтобы соответствующее значение было обновлено (в данном случае 1). Затем я хочу распечатать все текущие актуальные значения.

 hash = {"apple": 6, "banana": 2, "carrot": 3}

order = gets.chomp.downcase

hash.each do |key, value|
    if key.to_s == order
       value  = 1
       puts "Your order includes: #{value} #{key}."   
    end
end
  

Моя проблема в том, что я знаю, как напечатать только одну пару ключ-значение.

Например, если пользователь вводит «apple», я бы хотел, чтобы на выходе было написано: «Ваш заказ включает: 7 яблок, 2 банана, 3 моркови».

Комментарии:

1. Я думаю, вы хотели бы умножить «яблоко» на «яблоки», когда количество больше 1.

2. Помните, что вы можете искать вещи в хэше, вам не нужно прокручивать его и сравнивать. if (value = hash[order]) делает все это одним выстрелом. Подход, который у вас здесь, постепенно замедляется по мере увеличения количества элементов. Метод поиска занимает примерно одинаковое количество времени независимо от количества записей.

3. Суть проблемы здесь в том, что value = 1 хэш не обновляется. Вам нужно использовать Hash#[]=

Ответ №1:

 hash = {apple: 6, banana: 2, carrot: 3}
order = gets.chomp.downcase.to_sym
hash[order] = hash.fetch(order, 0)   1
puts "Your order includes: "   hash.map { |k, v| "#{v} #{k}" }.join(", ")
  

Некоторые примечания:

  • ваша инициализация хэша hash = {"apple": 6, "banana": 2, "carrot": 3} . ключи вашего хэша выглядят строками, но если вы используете этот синтаксис с двоеточием, они становятся символами. Итак, у вас есть два варианта. этот синтаксис:

     hash = {"apple" => 6, "banana" => 2, "carrot" => 3}
      

    или вы можете использовать символы, как я, и преобразовать пользовательский ввод в символ

  • что действительно здорово в hash, так это то, что вам не нужно перебирать элементы, чтобы найти то, что вы ищете. Существует сопоставление между ключами и значениями, поэтому легко найти и обновить значение

  • в третьей строке я имею дело с тем фактом, что ключ не может быть в хэше, fetch в этом случае у меня было 0. затем я увеличиваю и присваиваю обратно этому ключу

Ответ №2:

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

 hash = Hash.new(0).merge(apple: 6, banana: 2, carrot: 3)
hash[gets.chomp.downcase.to_sym]  = 1

puts "Your order includes: " <<
  hash.map { |k, v| [v, k].join(' ') }.join(', ')
  

или:

 puts hash.reduce("Your order includes: ") { |acc, (k, v)|
  acc << "#{v} #{k}, "
}[0..-3]
  

Ответ №3:

Рассмотрите возможность инициализации хэша, предоставляющего значение по умолчанию (Hash#default)

 basket = {'apple' => 6, 'banana' => 2, 'carrot' => 3}
basket.default = 0 # <-- set default 0 for start counting new keys
  

Определите метод представления данных:

 def show(basket)
  puts "Your order includes:"
  basket.each{ |key, value| puts "#{value}: #{key}" } 
end
  

Захват пользовательского ввода в цикле (объяснение в комментариях):

 loop do
  puts "Place your order:"
  order = gets.downcase.chomp # <-- format the input
  break if order == '0' # <-- breaks the input loop if this contition is matched
  next unless basket.has_key? order # <-- skip to next loop no matches with hash keys or remove this line if you want to count also non initialised keys
  basket[order]  = 1 # <-- increment by one the key
  show(basket) # <-- call the metod to show the basket
end

show(basket)