media
media

Reputation: 135

Ruby calculate the percentage of elements in hash

I have a hash :

hash = {"str1"=>2, "str2"=>3, "str3"=>7}

I want to calculate the percentage of each element in the hash so I can get one like this :

{"str1"=>16.66% , "str2"=>25.00%, "str3"=>58.33%}

Any idea about that? Thanks

Upvotes: 1

Views: 2552

Answers (3)

Mark Thomas
Mark Thomas

Reputation: 37517

The best answer IMHO was unfortunately deleted:

total = hash.values.sum
hash.transform_values { |v| (v * 100.0 / total).round(2) }

The hash method transform_values is relatively unknown and this case is exactly what it is for. (Ruby 2.4+ or Rails 4.2+)

@Ursus, if you undelete yours I'll delete this. Keep in mind that answers here are not just for OP but anyone else who has the same question in the future.

Upvotes: 5

media
media

Reputation: 135

Thanks to @AndreyDeineko for his quick answer! I tried to do it with an each method only (instead of each_with_object, so here is the answer.

sum = hash.values.sum
result = {}
hash.each { |k,v| result[k] = (v*100.00/sum).round(2)}

To have it with %:

hash.each { |k,v| result[k] = (v*100.00/sum).round(2).to_s + "%"}

Upvotes: 0

Andrey Deineko
Andrey Deineko

Reputation: 52357

You can use 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}

To have it with %:

a.each_with_object({}) { |(k, v), hash| hash[k] = "#{(v * 100.0 / sum).round(2)}%" }
#=> {"str1"=>"16.67%", "str2"=>"25.0%", "str3"=>"58.33%"}

Upvotes: 6

Related Questions