假设我有一个数组:
array = [["male", 59], ["female", 31], ["unknown gender", 38]]
数组中的数字是按性别划分的用户总数。我需要做的是获取数组的每个元素,找到每个男性,女性和未知的平均值,并将它们放入一个如下所示的新数组中:
new_array = [["male", 46], ["female", 24], ["unknown gender", 30]]
元组内的第二个值是平均值。
我尝试过这样设置:
new_array = []
sum = 0
array.each do |k,v|
sum += v
new_array << [k,(v/sum)*100]
end
我的新阵列结果却是[["male", 100], ["female", 0], ["unknown gender", 0]]
我尝试了一些不同的东西,无法弄清楚我做错了什么。任何帮助都会很棒。
答案 0 :(得分:1)
这里有两个问题。
首先是你在(v/sum)
进行整数除法。结果可能不是您所期望的,因此您应该将v
变为浮动:(v.to_f/sum)
。
第二个问题是,在实际包含总和之前,您正在使用sum
变量。
将这两者放在一起:
array = [["male", 59], ["female", 31], ["unknown gender", 38]]
new_array = []
sum = 0
# calculating sum before it's used in division below.
array.each { |_, v| sum += v }
array.each do |k, v|
new_array << [k, ((v.to_f / sum) * 100).round]
end
# => [["male", 46], ["female", 24], ["unknown gender", 30]]
答案 1 :(得分:0)
你需要做一些事情。现在发生的事情是总和是59. v / 59是第一次迭代中的一个。在第二次迭代31/90 == 0,因为您没有将总和除以迭代次数。你真正想要的是31/45,因为45是90/2(2是迭代次数)
1)您需要将总和除以迭代次数以获得当前平均值。
2)你的语法
array.each do |k,v|
具有误导性,因为您不处理键和值,而是处理数组索引。
答案 2 :(得分:0)
我更喜欢使用更专业的Ruby方法,例如inject
或map
,而不是简单的each
:
array = [['male', 59], ['female', 31], ['unknown gender', 38]]
total = array.inject(0) { |sum, (_, n)| sum + n }
new_array = array.map { |k, v| [k, ((v.to_f / total) * 100).round] }
#=> [["male", 46], ["female", 24], ["unknown gender", 30]]
此外,((v.to_f / total) * 100).round
部分可以像这样提取到自己的方法中:
def percentage(value, total)
((value.to_f / total) * 100).round
end
是什么让map
更具可读性:
new_array = array.map { |k, v| [k, percentage(v, total)] }
答案 3 :(得分:0)
如果您有选择,我建议您考虑使用哈希而不是数组和符号而不是字符串:
hash = { male: 59, female: 31, unknown_gender: 38 }
#=> {:male=>59, :female=>31, :unknown_gender=>38}
tot = hash.values.reduce(:+)
#=> 128
percents = hash.each_with_object({}) { |(k,v),h| h[k] = (100.0*v/tot).round }
#=> {:male=>46, :female=>24, :unknown_gender=>30}