Ruby 从数组数组中获取平均值

Ruby 从数组数组中获取平均值,ruby,arrays,Ruby,Arrays,我有一个类似于以下内容的数组: [["Timmy", "90", "47", "89"], ["Simon", "89", "57", "99"]] (etc) 我需要遍历每个子数组,将每个子数组中的数字相加,并给出每个子数组的平均值 我不知道如何访问每个号码。任何帮助都将不胜感激 以下是一个可能的解决方案: arr = [["Timmy", "90", "47", "89"], ["Simon", "89", "57", "99"]] averages = arr.map do |name,

我有一个类似于以下内容的数组:

[["Timmy", "90", "47", "89"], ["Simon", "89", "57", "99"]] (etc)
我需要遍历每个子数组,将每个子数组中的数字相加,并给出每个子数组的平均值


我不知道如何访问每个号码。任何帮助都将不胜感激

以下是一个可能的解决方案:

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设置为数组中的第一个元素,nums设置为数组的其余部分减去name


nums.map&:to_f.inject:+将每个字符串转换为浮点数,然后除以nums中的元素数以创建平均值。

以下是一种可能的解决方案:

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设置为数组中的第一个元素,nums设置为数组的其余部分减去name


nums.map&:to_f.inject:+将每个字符串转换为一个浮点数,然后除以nums中的元素数以创建平均值。

稍有不同且速度稍快的变体:

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]]
使用初始为0的累加器注入。然后将转换为Float的每个num添加到它

基准:

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)

稍有不同且速度稍快的变体:

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]]
使用初始为0的累加器注入。然后将转换为Float的每个num添加到它

基准:

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)


每个子阵列中数字的平均值,或所有子阵列的平均值?每个子阵列中数字的平均值。很抱歉“为什么这听起来像家庭作业?”天门,这是我正在做的家庭作业的一小部分。从CSV文件中读取数据给了我一个带有子数组的数组,这是我们从未使用过的。我没有公布我的全部作业,而是请求帮助阅读数组,然后创建一个新数组。你知道,有时候像你这样的人会有点太激动了。我得到的答案不仅解释了一切是如何工作的,还向我介绍了Ruby中一些我从未使用过的新东西。我学到的比我自己学到的多得多。前地图,地图!,你不了解我,也不知道我是否激动。你可能想读书。你会发现这本书非常有趣,它会让你理解为什么很多人想要公开家庭作业问题,并且可能不想帮助回答这些问题。这是一个数字。每个子数组中数字的平均值,或者所有子数组的平均值?每个子数组中数字的平均值。很抱歉“为什么这听起来像家庭作业?”天门,这是我正在做的家庭作业的一小部分。从CSV文件中读取数据给了我一个带有子数组的数组,这是我们从未使用过的。我没有公布我的全部作业,而是请求帮助阅读数组,然后创建一个新数组。你知道,有时候像你这样的人会有点太激动了。我得到的答案不仅解释了一切是如何工作的,还向我介绍了Ruby中一些我从未使用过的新东西。我学到的比我自己学到的多得多。前地图,地图!,你不了解我,也不知道我是否激动。你可能想读书。你会发现这本书非常有趣,它会让你理解为什么很多人想要公开家庭作业问题,并且可能不想帮助回答这些问题。下面是一些。除了可能添加之外,很难对此进行改进。第2轮:-。如果你不知道可怜的Timmy在阵列中的位置,你可以改变[name,*nums | to |*nums |。啊,是的,并更改为nums.lenght-1`,正如您所说。@CarySwoveland-如果您不知道名称在哪里,但您确实知道数组中的某个地方有一个名称,您可以执行类似于nums.map&:to|f.inject:+/nums.length-1的操作,因为Timmy.to|f将被计算为0…在该块后执行arr的puts操作,我仍在获取原始数组。有什么想法吗?@Destiny map不会更改原始数组。我已经修改了答案,将结果分配给一个新的变量平均值。如果您想更改原始数组,请使用而不是Mapah。这很有意义。非常感谢!除了可能添加之外,很难对此进行改进。round2:-。如果你不知道可怜的Timmy在阵列中的位置你可以换个[name,*nums | to |*nums |。啊,是的,并更改为nums.lenght-1`,正如您所说。@CarySwoveland-如果您不知道名称在哪里,但您确实知道数组中的某个地方有一个名称,您可以执行类似于nums.map&:to|f.inject:+/nums.length-1的操作,因为Timmy.to|f将被计算为0…在该块后执行arr的puts操作,我仍在获取原始数组。有什么想法吗?@Destiny map不会更改原始数组。我已经修改了答案,将结果分配给一个新的变量平均值。如果你想更改原始数组-使用而不是m
阿帕赫。那就有道理了。非常感谢你!