【问题标题】:Nested Hash summing value based on key ruby [closed]基于键 ruby​​ 的嵌套哈希求和值 [关闭]
【发布时间】:2018-03-08 07:39:16
【问题描述】:

有没有更聪明的方法来汇总所有键的值:

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}

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

【问题讨论】:

  • 你的尝试是什么样的?只是为了让我知道我没有发布相同的答案。
  • 不得不说,ab 在这里表示 3 个不同的东西这一事实对可读性没有帮助。
  • (at)ndn 感谢您的回答,我已更正。 @sagar-pandya 我试图将个人总数相加以获得上述哈希的总数。

标签: ruby


【解决方案1】:
a.
  values.
  flat_map(&:values).
  flat_map(&:to_a).
  each_with_object({}) { |(key, value), b| b[key] = b[key].to_i + value }

【讨论】:

    【解决方案2】:
    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}
    

    【讨论】:

      【解决方案3】:

      您可以改进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了解更多详情。

      【讨论】:

      • 感谢您的详尽回答
      • @FerdinandRosario 欢迎您。如果您有任何问题,我很乐意回答。
      • 有些人从智能手机/平板电脑上阅读 SO。请通过分割很长的行来尊重它们以避免水平滚动。
      • @mudasobwa 我不明白你的意思。这听起来无关紧要。大多数智能手机/平板电脑都可以通过一点滚动来完成。无论如何,这种改进假设通过计算机检查它,如果它有更多的行而不是长的行,就不会更容易理解它。而且……是的,我确实尊重他人。专门为您将长线分成 3 条。
      猜你喜欢
      • 2013-09-30
      • 2015-06-13
      • 2014-04-23
      • 2015-05-10
      • 2021-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-22
      相关资源
      最近更新 更多