У меня есть хэш:
hash = {"str1"=>2, "str2"=>3, "str3"=>7}
Я хочу рассчитать процент каждого элемента в хэше, чтобы получить его следующим образом:
{"str1"=>16.66% , "str2"=>25.00%, "str3"=>58.33%}
Любая идея об этом? Спасибо
У меня есть хэш:
hash = {"str1"=>2, "str2"=>3, "str3"=>7}
Я хочу рассчитать процент каждого элемента в хэше, чтобы получить его следующим образом:
{"str1"=>16.66% , "str2"=>25.00%, "str3"=>58.33%}
Любая идея об этом? Спасибо
Вы можете использовать Enumerable#each_with_object
:
sum = a.values.inject(0, :+) # or simply a.values.sum if you're on Ruby 2.4+
#=> 12
a.each_with_object({}) { |(k, v), hash| hash[k] = v * 100.0 / sum }
#=> {"str1"=>16.666666666666668, "str2"=>25.0, "str3"=>58.333333333333336}
Чтобы иметь это с %
:
a.each_with_object({}) { |(k, v), hash| hash[k] = "#{(v * 100.0 / sum).round(2)}%" }
#=> {"str1"=>"16.67%", "str2"=>"25.0%", "str3"=>"58.33%"}
round(2)
, чтобы получить только 2 числа после комы. Не могли бы вы объяснить больше { |(k, v), hash| hash[k] =
, чтобы я мог лучше понять .. Спасибо
- person media; 09.05.2017
k
,v
) и создаете новый объект на лету ({})
- хеш. Таким образом, перед первой итерацией хэш пуст (это начальное значение, которое мы дали). На первой итерации мы устанавливаем hash["str1"]
равным расчетному проценту на основе v
(2
). На следующей итерации мы устанавливаем hash["str2"]
для следующего расчета и так далее. В итоге у нас есть новый хэш-объект.
- person Andrey Deineko; 09.05.2017
'%.2f%' % (v * 100.0 / sum)
может быть более читабельным, если вы привыкли к sprintf.
- person Eric Duminil; 09.05.2017
'%.2f%'
напоминает мне Java, которую я не очень люблю. Но на самом деле это может выглядеть чище для тех, кто к этому привык.
- person Andrey Deineko; 09.05.2017
sum
равно нулю.
- person Cary Swoveland; 14.05.2017
Лучший ответ ИМХО был, к сожалению, удален:
total = hash.values.sum
hash.transform_values { |v| (v * 100.0 / total).round(2) }
Метод хеширования transform_values
относительно неизвестен, и именно для этого случая он и предназначен. (Ruby 2.4+ или Rails 4.2+)
@Ursus, если ты восстановишь свое, я удалю это. Имейте в виду, что ответы здесь предназначены не только для OP, но и для всех, у кого возникнет такой же вопрос в будущем.
transform_values
, который слишком нов, чтобы использовать его в ответе без альтернативы :)
- person Ursus; 09.05.2017
Спасибо @AndreyDeineko за быстрый ответ! Я пытался сделать это только методом each
(вместо each_with_object
, так что вот ответ.
sum = hash.values.sum
result = {}
hash.each { |k,v| result[k] = (v*100.00/sum).round(2)}
Чтобы иметь это с %
:
hash.each { |k,v| result[k] = (v*100.00/sum).round(2).to_s + "%"}
Hash#transform_values
. - person Sagar Pandya   schedule 09.05.2017