【问题标题】:Join common keys in hash one-liner加入哈希单行中的公共键
【发布时间】:2011-09-11 07:00:21
【问题描述】:

我有这个数组:

[{"a"=>"1"}, {"b"=>"2"}, {"a"=>"3"}, {"b"=>"4"}, {"a"=>"5"}]

我想要一种方法将具有多个值的共同键合并到:

[{"a"=>["1","3","5"]}, {"b"=>["2","4"]}]

【问题讨论】:

    标签: ruby arrays join hash merge


    【解决方案1】:
    array = [{"a"=>"1"}, {"b"=>"2"}, {"a"=>"3"}, {"b"=>"4"}, {"a"=>"5"}]
    {}.tap{ |r| array.each{ |h| h.each{ |k,v| (r[k]||=[]) << v } } }
    

    【讨论】:

    • 第一个不是 1 班轮。其次它不会产生所需的输出
    【解决方案2】:

    还没有尝试过,但类似的东西应该也可以工作

       a.each_with_object( Hash.new{ |h,k| h[k] = [] } ) do |x, hash|
          hash[x.keys.first] << x.values.first
       end
    

    编辑:对于一个衬里,以及相同的输出:

    [a.each_with_object( Hash.new{ |h,k| h[k] = [] } ) { |x, hash| hash[x.keys.first] << x.values.first }]
    

    【讨论】:

      【解决方案3】:

      根据 Marc-Andre 的建议进行了改进。

      array = [{"a"=>"1"}, {"b"=>"2"}, {"a"=>"3"}, {"b"=>"4"}, {"a"=>"5"}]
      array.group_by(&:keys).map{|k, v| {k.first => v.flat_map(&:values)}}
      

      或者

      array.group_by{|h| h.keys.first}.each_value{|a| a.map!{|h| h.values.first}}
      

      【讨论】:

        【解决方案4】:

        解决您的问题:

        array.map(&:first).group_by(&:first).map{|k, v| {k => v.map(&:last)}}
        

        我很好奇为什么你以只包含一个密钥对的哈希开始和结束。数组会更适合。例如:

        other = [["a", "1"], ["b", "2"], ["a", "3"], ["b", "4"], ["a", "5"]]
        r = other.group_by(&:first).map{|k, v| [k => v.map(&:last)]}
        r  # => [["a", ["1", "3", "5"]], ["b", ["2", "4"]]]
        Hash[r] # => {"a"=>["1", "3", "5"], "b"=>["2", "4"]}
        

        【讨论】:

        • 您使用Hash#first 将哈希转换为数组很酷。
        【解决方案5】:

        不确定您是否为了简洁而颁发奖项,但我喜欢这种方式。带有块的合并功能非常适合这种情况:

        new = {}
        array.each {|p| new.merge!(p) {|k,l,r| [l,r].flatten }}
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-05-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多