我有一个与此类似的数组:
[["Timmy", "90", "47", "89"], ["Simon", "89", "57", "99"]] (etc)
我需要遍历每个子数组并总计每个子数组中的数字并给出每个子数组的平均值。
我不确定如何访问每个号码。任何帮助将不胜感激!
答案 0 :(得分:6)
这是一个可能的解决方案:
arr = [["Timmy", "90", "47", "89"], ["Simon", "89", "57", "99"]]
averages = arr.map do |name, *nums|
[name, nums.map(&:to_f).inject(:+) / nums.length]
end
# => [["Timmy", 75.33333333333333], ["Simon", 81.66666666666667]]
此解决方案使用ruby的列表推导,因此arr
中的每个元素都在参数|name, *nums|
的块上运行,name
设置为数组中的第一个元素,{ {1}}设置为数组的其余部分(减去nums
)。
name
将每个字符串转换为浮点数,然后将其除以nums.map(&:to_f).inject(:+)
中的元素数以创建平均值。
答案 1 :(得分:0)
有点不同,而且变化稍快一些:
arr = [["Timmy", "90", "47", "89"], ["Simon", "89", "57", "99"]]
averages = arr.map do |name, *nums|
[name, nums.inject(0){|acc, el| acc + el.to_f} / nums.length]
end
p averages
# => [["Timmy", 75.33333333333333], ["Simon", 81.66666666666667]]
将inject
与最初为0的累加器一起使用。然后将每个num转换为Float。
基准:
require 'benchmark'
arr = [["Timmy", "90", "47", "89"], ["Simon", "89", "57", "99"]]
n = 1_000_000
Benchmark.bm do |x|
x.report("map.inject : ") { n.times do ; arr.map do |name, *nums| ; [name, nums.map(&:to_f).inject(:+) / nums.length] ; end ; end }
x.report("inject(acc): ") { n.times do ; arr.map do |name, *nums|; [name, nums.inject(0){|ac,el| ac +el.to_f} / nums.length]; end ; end }
end
#=> user system total real
#=> map.inject : 2.220000 0.000000 2.220000 ( 2.218477)
#=> inject(acc): 2.030000 0.000000 2.030000 ( 2.031263)