You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对结构相同的Ruby嵌套哈希数组计算平均值?

问题

现有结构完全一致的嵌套哈希数组如下:

array = [
  {
    "id": 8444,
    "version": "2.1.0",
    "data": {
      "data1": {
        "data1-1": {
          "a": 132.6,
          "b": 128.36,
          "c": 153.59,
          "d": 136.48
        }
      },
      "data2": {
        "data2-1": {
          "a": 1283.0,
          "b": 1254.0,
          "c": 1288.5,
          "d": 1329.0
        }
      }
    }
  },
  {
    "id": 8443,
    "version": "2.1.0",
    "data": {
      "data1": {
        "data1-1": {
          "a": 32.6,
          "b": 28.36,
          "c": 53.59,
          "d": 36.48
        }
      },
      "data2": {
        "data2-1": {
          "a": 283.0,
          "b": 254.0,
          "c": 288.5,
          "d": 329.0
        }
      }
    }
  },
  {
    "id": 8442,
    "version": "2.1.0",
    "data": {
      "data1": {
        "data1-1": {
          "a": 32.6,
          "b": 28.36,
          "c": 53.59,
          "d": 36.48
        }
      },
      "data2": {
        "data2-1": {
          "a": 283.0,
          "b": 254.0,
          "c": 288.5,
          "d": 329.0
        }
      }
    }
  }
]

需要生成一个与原哈希中data结构完全相同的新哈希,其中a、b、c、d的取值为数组中对应位置所有值的平均值。

预期结果:

{
  "data1": {
    "data1-1": {
      "a": 65.9,
      "b": 61.7,
      "c": 86.9,
      "d": 69.8
    }
  },
  "data2": {
    "data2-1": {
      "a": 616.3,
      "b": 587.3,
      "c": 621.8,
      "d": 662.3
    }
  }
}

尝试了以下代码,但仅保留了最后一个元素的data值,未实现累加平均:

array.reduce({}) do |acc, hash|
  hash[:data].each do |k,v|
    acc[k] = v
  end
end
# => {:data1=>{"data1-1"=>{:a=>32.6, :b=>28.36, :c=>53.59, :d=>36.48}}, 
#     :data2=>{"data2-1"=>{:a=>283.0, :b=>254.0, :c=>288.5, :d=>329.0}}}
最优实现方案

由于数组中每个元素的data结构完全一致,核心思路是先累加所有对应位置的数值,再除以数组长度得到平均值。这里提供两种方案:

方案1:固定层级遍历(性能最优,适合已知结构)

如果哈希的嵌套层级固定,可以直接逐层遍历累加:

n = array.size

# 初始化累加哈希,结构与第一个元素的data一致,所有数值设为0.0
sum_hash = Marshal.load(Marshal.dump(array.first[:data])).tap do |h|
  h[:data1][:"data1-1"].transform_values! { 0.0 }
  h[:data2][:"data2-1"].transform_values! { 0.0 }
end

# 遍历数组,累加所有对应位置的数值
array.each do |item|
  item[:data].each do |top_key, top_val|
    top_val.each do |sub_key, sub_val|
      sub_val.each do |k, v|
        sum_hash[top_key][sub_key][k] += v
      end
    end
  end
end

# 计算平均值得到最终结果
result = sum_hash.each_with_object({}) do |(top_key, top_val), acc|
  acc[top_key] = top_val.each_with_object({}) do |(sub_key, sub_val), sub_acc|
    sub_acc[sub_key] = sub_val.transform_values { |v| v / n }
  end
end

puts result.inspect

方案2:递归遍历(通用灵活,适配任意嵌套层级)

如果哈希的嵌套层级可能变化,递归方法更通用,无需硬编码层级:

# 递归累加嵌套哈希的对应值
def deep_sum(acc, current)
  current.each do |k, v|
    if v.is_a?(Hash)
      acc[k] ||= {}
      deep_sum(acc[k], v)
    else
      acc[k] ||= 0.0
      acc[k] += v
    end
  end
end

# 递归计算平均值
def deep_average(sum_hash, n)
  sum_hash.each_with_object({}) do |(k, v), acc|
    acc[k] = v.is_a?(Hash) ? deep_average(v, n) : v / n
  end
end

n = array.size
sum_hash = {}
array.each { |item| deep_sum(sum_hash, item[:data]) }
result = deep_average(sum_hash, n)

puts result.inspect

错误代码分析

之前的reduce代码仅做了覆盖赋值:每次循环都用当前元素的data值替换累加器中的对应键,最终只保留了最后一个元素的data,完全没有进行数值累加,因此无法得到平均值。

内容的提问来源于stack exchange,提问作者SJU

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 11:10:48