Попытка вычесть все значения в хэше из переменной

#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. Привет, Игиан, спасибо за вашу помощь. Очень признателен 🙂