基于关键ruby的嵌套Hash求和值

时间:2018-03-08 07:39:16

标签: ruby

是否有一种更智能的方法可以将所有键值相加:

hash_1 = {
  41 => {"a" => {:a => 4, :b => 8, :c => 3}},
  56 => {"b" => {:a => 5, :b => 4, :c => 8}},
  57 => {"c" => {:a => 8, :b => 9, :c => 3}},
}

得到结果:

result_hash = {a: 17, b: 21, c: 14}

我可以通过迭代每个哈希获得上面的结果,但我正在寻找另一种方法来实现它。

3 个答案:

答案 0 :(得分:3)

a.
  values.
  flat_map(&:values).
  flat_map(&:to_a).
  each_with_object({}) { |(key, value), b| b[key] = b[key].to_i + value }

答案 1 :(得分:3)

hash_1.map { |_, v| v.to_a.last.last }.
       reduce { |e, acc| acc.merge(e) { |_, v1, v2| v1 + v2 } }
#⇒ {:a=>17, :b=>21, :c=>14}

答案 2 :(得分:1)

您可以改进Hash::each,以便您轻松执行任务:

module HashRecursive
    refine Hash do
        def each(recursive=false, &block)
            if recursive
                Enumerator.new do |yielder|
                    self.map do |key, value|
                        value.each(recursive=true).map{ |key_next, value_next|
                            yielder << [[key, key_next].flatten, value_next]
                        } if value.is_a?(Hash)
                        yielder << [[key], value]
                    end
                end.entries.each(&block)
            else
                super(&block)
            end
        end
        alias_method(:each_pair, :each)
    end
end
using HashRecursive

以下是您的任务的解决方案:

def sum_hashes(hash)        # This method will do the job
    result_hash = {}

    hash.each(recursive=true) do |keys, value|
        if keys.size == 2
            result_hash.merge!(value) do |key, value1, value2|
                [value1, value2].all? {|v| v.is_a?(Integer)} ? value1+value2 : value2
            end
        end
    end

    result_hash
end

# Here is your question's example

hash_1 = {
    41  =>  {"a" => {:a => 4, :b => 8, :c => 3}},
    56  =>  {"b" => {:a => 5, :b => 4, :c => 8}},
    57  =>  {"c" => {:a => 8, :b => 9, :c => 3}}
}
puts sum_hashes(hash_1)     # {:a=>17, :b=>21, :c=>14}

# This will work for anything that has similar pattern

hash_2 = {
    :a      =>  { "p"   =>  {:a =>  1, :b   =>  2, :c   =>  0,      :d  =>  5   }},
    3       =>  { "b"   =>  {:a =>  2, :b   =>  2, :c   =>  100,    :d  =>  0   }},
    404     =>  { "c"   =>  {:a =>  3, :b   =>  2, :c   =>  -100,   :d  =>  15  }},
    '24'    =>  { "2"   =>  {:a =>  4, :b   =>  2, :c   =>  300,    :d  =>  25  }},
    11      =>  { :h    =>  {:a =>  5, :b   =>  2, :c   =>  -350,   :d  =>  40  }},
    :x      =>  { "c"   =>  {:a =>  6, :b   =>  2, :c   =>  50,     :d  =>  5   }}
}
puts sum_hashes(hash_2)     # {:a=>21, :b=>12, :c=>0, :d=>90}

请查看this answer了解详情。