Ruby on rails Ruby group_由具有不同键的哈希数组组成(键不是固定的)

Ruby on rails Ruby group_由具有不同键的哈希数组组成(键不是固定的),ruby-on-rails,ruby,Ruby On Rails,Ruby,我想将哈希数组分组为: array = [{"value"=>[{"a"=>1},{"b"=>4}]},{"value"=>[{"c"=>4},{"d"=>3},{"a"=>3},{"b"=>54}]}] 致: 我可以将数组转换为 array1=[{a=>1},{b=>4},{c=>4},{d=>3},{a=>3},{b=>54}]使用array.map&:values.flatte。我可以通过对所有数据进行循环,将数组1转换为哈希分组的数据。但

我想将哈希数组分组为:

array = [{"value"=>[{"a"=>1},{"b"=>4}]},{"value"=>[{"c"=>4},{"d"=>3},{"a"=>3},{"b"=>54}]}]
致:

我可以将数组转换为 array1=[{a=>1},{b=>4},{c=>4},{d=>3},{a=>3},{b=>54}]使用array.map&:values.flatte。我可以通过对所有数据进行循环,将数组1转换为哈希分组的数据。但我需要一种更有效的方法,比如使用组_,因为过动态的键是不固定的


我知道如何分组,如果关键是固定的。我需要根据动态更改的键对您进行分组。

这里有一个有趣的数据结构:D

各自
但是请注意,输出是不同的。如果一个字母只有一个值,它将作为整数返回,而不是作为一个1元素数组返回。

我不希望因为这一个而获得任何可读性奖

array.map(&:values)
     .flatten
     .group_by { |o| o.keys.first }
     .map { |key, v| [key, v.map(&:values).flatten] }
     .to_h
=> {"a"=>[1, 3], "b"=>[4, 54], "c"=>[4], "d"=>[3]}
如果有人好奇,我会列出一些粗略的基准:

require 'benchmark'

n = 10000
letters = ('a'...'z').to_a
numbers = (0...1000).to_a

built_array = []
n.times do |i|
  values = []
  obj_size = (1...letters.size).to_a.sample
  obj_size.times do |j|
    values << {
      "#{letters.sample}" => numbers.sample
    }
  end
  built_array << { "value" => values }
end

Benchmark.bm(15) do |x|
  x.report("anthony") { anthony(built_array) }
  x.report("eric each") { eric_each(built_array) }
  x.report("eric ewo") { eric_each_with_object(built_array) }
  x.report("eric merge") { eric_merge(built_array) }
  x.report("ed inject") { ed_inject(built_array) }
end

                      user     system      total        real
anthony           0.130000   0.010000   0.140000 (  0.146601)
eric each         0.060000   0.000000   0.060000 (  0.067160)
eric ewo          0.070000   0.000000   0.070000 (  0.076125)
eric merge       25.250000   0.880000  26.130000 ( 28.297592)
ed inject         0.080000   0.010000   0.090000 (  0.111045)

我同意埃里克·杜米尼尔的观点。有趣的数据结构

注入
确实没有可读性奖,但这是真正的Ruby方式。谢谢分享!我总是在这里学到很多东西。很好的选择。我运行了一些基准测试,每个测试都是最快的,您的合并解决方案几乎无法完成大于100000的阵列
grouped_data = Hash.new { |h, k| h[k] = [] }

p array.map(&:values).flatten.each_with_object(grouped_data){|subhash,data| 
  subhash.each do |k,v|
    data[k] << v
  end
}
#=> {"a"=>[1, 3], "b"=>[4, 54], "c"=>[4], "d"=>[3]}
p array.map(&:values).flatten.inject{|mem,hash| mem.merge(hash){|k,o,n| [o,n].flatten}}
#=> {"a"=>[1, 3], "b"=>[4, 54], "c"=>4, "d"=>3}
array.map(&:values)
     .flatten
     .group_by { |o| o.keys.first }
     .map { |key, v| [key, v.map(&:values).flatten] }
     .to_h
=> {"a"=>[1, 3], "b"=>[4, 54], "c"=>[4], "d"=>[3]}
require 'benchmark'

n = 10000
letters = ('a'...'z').to_a
numbers = (0...1000).to_a

built_array = []
n.times do |i|
  values = []
  obj_size = (1...letters.size).to_a.sample
  obj_size.times do |j|
    values << {
      "#{letters.sample}" => numbers.sample
    }
  end
  built_array << { "value" => values }
end

Benchmark.bm(15) do |x|
  x.report("anthony") { anthony(built_array) }
  x.report("eric each") { eric_each(built_array) }
  x.report("eric ewo") { eric_each_with_object(built_array) }
  x.report("eric merge") { eric_merge(built_array) }
  x.report("ed inject") { ed_inject(built_array) }
end

                      user     system      total        real
anthony           0.130000   0.010000   0.140000 (  0.146601)
eric each         0.060000   0.000000   0.060000 (  0.067160)
eric ewo          0.070000   0.000000   0.070000 (  0.076125)
eric merge       25.250000   0.880000  26.130000 ( 28.297592)
ed inject         0.080000   0.010000   0.090000 (  0.111045)
array = [{"value"=>[{"a"=>1},{"b"=>4}]},{"value"=>[{"c"=>4},{"d"=>3},{"a"=>3},{"b"=>54}]}]

new_hash = array.inject(Hash.new) do |h,o|
  o['value'].each do |sh|
    h[sh.keys[0]] = [] if h[sh.keys[0]].nil?
    h[sh.keys[0]] << sh.values[0] 
  end
  h
end

puts new_hash
#=> {"a"=>[1, 3], "b"=>[4, 54], "c"=>4, "d"=>3}