#ruby
#ruby
Вопрос:
Недавно я начал изучать программирование на ruby. В настоящее время я застрял на хэше, где я пытаюсь вычесть каждое значение хэша из общей суммы. Пока он вычитает только из последнего значения хэша.
categories_hash = {
"Bills" => 100,
"Utilities" => 150,
"Groceries" => 200
}
balance = 500
categories_hash.each do |k, v|
$new_balance = balance - v
end
puts $new_balance
Результат, который я ожидаю, должен быть 50, но я получаю 300. Кажется, что из баланса вычитается только последнее значение.
Я также пытался:
$new_balance = balance - categories_hash.values
Однако это затем выдает мне сообщение об ошибке «Массив не может быть преобразован в целое число».
Каков наилучший способ для меня решить эту проблему?
Комментарии:
1. Старайтесь держаться подальше, подальше от глобальных переменных, таких как
$new_balance
. Вместо этого просто используйте обычные переменные, без$
префикса. Причина, по которой это проблема, заключается в том, что они являются глобальными для всей вашей программы и могут быть легко неправильно использованы другими частями вашего кода, если их случайно не затоптали и не переназначили.2. Быстрое исправление здесь находится
balance -= v
вeach
цикле.3. @Maxx : поскольку вы никогда не изменяете
balance
и всегда вычисляете$new_balance
из fresh в цикле, конечное значение$new_balance
будет простоbalance - categories_hash["Groceries"]
. Это не особая проблема Ruby (за исключением того факта, что Ruby гарантирует порядок, в котором обрабатываются элементы хэша), а основная проблема вашего алгоритма. Вы столкнулись бы с той же проблемой, если бы кодировали ее на другом языке.
Ответ №1:
Нет необходимости извлекать значения из хэша перед их суммированием:
balance - categories_hash.sum(amp;:last) #=> 50
Альтернативно,
-categories_hash.sum(-balance, amp;:last) #=> 50
См. Array#sum .
Комментарии:
1. Привет, Кэри, спасибо за ваш ответ и помощь, я очень ценю это 🙂
Ответ №2:
$new_balance = balance - categories_hash.values.sum
Поскольку values — это массив, вам нужно суммировать его перед вычитанием из balance
Комментарии:
1. Привет, Агунг, большое вам спасибо за ваш ответ, и я только что попробовал, и он отлично сработал. Спасибо 🙂
2. @Maxx не беспокойтесь.
Ответ №3:
Вы также можете использовать inject
метод для требования, как показано ниже
categories_hash = {
"Bills" => 100,
"Utilities" => 150,
"Groceries" => 200
}
# working inject with values(Array)
balance = 500
categories_hash.values.inject(balance, :-)
#=> 50
# working inject with directly (Hash)
balance = 500
categories_hash.inject(balance){|b, val| b-= val.last}
#=> 50
Комментарии:
1. Или
categories_hash.inject(balance) { |b, (_, v)| b - v }
который использует разложение массива для пары ключ-значение. Вам также не нужно-=
, просто-
Ответ №4:
Придерживаясь вашего первого примера, просто обновите balance
внутри цикла:
balance = 500
old_balance = balance # backup just in case
categories_hash.each do |_, v|
balance -= v
end
balance #=> 50
old_balance #=> 500
Где balance -= v
то же самое, что и balance = balance - v
Для более короткой версии кода обратитесь к другим ответам в этой теме.
Комментарии:
1. Привет, Игиан, спасибо за вашу помощь. Очень признателен 🙂