【问题标题】:How to merge array of hash of array of hash on condition?如何在条件下合并哈希数组的哈希数组?
【发布时间】:2016-03-30 21:28:00
【问题描述】:

如果数组具有相同的值,但目标是合并数组,但会继承其中的现有哈希数组。

到目前为止的代码:

aff_packages = [{:platform=>"platform 5", :pkg=>"package1", :state=>"somestate"},
                {:platform=>"platform 7", :pkg=>"package2", :state=>"somestate"},
                {:platform=>"platform 5", :pkg=>"package3", :state=>"somestate"},
                {:platform=>"platform 5", :pkg=>"package4", :state=>"somestate"},
                {:platform=>"platform 7", :pkg=>"package5", :state=>"somestate"},
                {:platform=>"platform 6", :pkg=>"package6", :state=>"somestate"
                }]

  aff_packages.each do |package|

    small_array = []
    print_me = big_array = []
    hash = Hash.new
    print_me << hash

    small_array << {
        package: package[:pkg],
        state:  package[:state]
    }

    (hash[package[:platform]] ||= small_array)

    end

产生:

[{"platform 5"=>[{:package=>"package1", :state=>"somestate"}]}]
[{"platform 7"=>[{:package=>"package2", :state=>"somestate"}]}]
[{"platform 5"=>[{:package=>"package3", :state=>"somestate"}]}]
[{"platform 5"=>[{:package=>"package4", :state=>"somestate"}]}]
[{"platform 7"=>[{:package=>"package5", :state=>"somestate"}]}]
[{"platform 6"=>[{:package=>"package6", :state=>"somestate"}]}]

我怎样才能将相同的平台合并在一起,但继承哈希数组并像这样附加它:

[{"platform 5"=>[{:package=>"package1", :state=>"somestate"}], [{:package=>"package3", :state=>"somestate"}], [{:package=>"package4", :state=>"somestate"}]}]
[{"platform 7"=>[{:package=>"package2", :state=>"somestate"}], [{:package=>"package5", :state=>"somestate"}]}]
[{"platform 6"=>[{:package=>"package6", :state=>"somestate"}]}]

【问题讨论】:

  • 您的预期结果无效。

标签: arrays ruby hash merge


【解决方案1】:

这是一种可能的解决方案。

您的代码给出的输入:

aff_packages = [{:platform=>"platform 5", :pkg=>"package1", :state=>"somestate"},
                {:platform=>"platform 7", :pkg=>"package2", :state=>"somestate"},
                {:platform=>"platform 5", :pkg=>"package3", :state=>"somestate"},
                {:platform=>"platform 5", :pkg=>"package4", :state=>"somestate"},
                {:platform=>"platform 7", :pkg=>"package5", :state=>"somestate"},
                {:platform=>"platform 6", :pkg=>"package6", :state=>"somestate"
                }]

第 1 步:创建以平台为键、其余属性为值的哈希

ary = aff_packages.map do |package|
    # Let's create a copy as we don't want to modify aff_packages
    pkg = package.dup

    # Remove :platform's value from pkg hash
    platform = pkg.delete(:platform)

    # Return platform name and rest of hash as key-value
    { platform => pkg }
end

此时ary是一个哈希数组,如下图:

[{"platform 5"=>{:pkg=>"package1", :state=>"somestate"}}, 
 {"platform 7"=>{:pkg=>"package2", :state=>"somestate"}}, 
 {"platform 5"=>{:pkg=>"package3", :state=>"somestate"}}, 
 {"platform 5"=>{:pkg=>"package4", :state=>"somestate"}}, 
 {"platform 7"=>{:pkg=>"package5", :state=>"somestate"}}, 
 {"platform 6"=>{:pkg=>"package6", :state=>"somestate"}}]

第 2 步:我们现在有了散列数组,让我们合并散列,这样对于给定的键,值被收集为数组。

h = ary.reduce(Hash.new{|hash, k| hash[k] = []}) do |memo, i| 
    memo[i.keys.first] << i.values.first; memo 
end

请注意,我们使用Enumerable#reduce 来收集新Hash 中的值。另外,请注意 Hash#new 的块语法的使用,它允许为每个键设置空数组的默认值。

此时,我们有哈希h,其值如下所示。

{"platform 5"=>
  [{:pkg=>"package1", :state=>"somestate"},
   {:pkg=>"package3", :state=>"somestate"},
   {:pkg=>"package4", :state=>"somestate"}],
 "platform 7"=>
  [{:pkg=>"package2", :state=>"somestate"},
   {:pkg=>"package5", :state=>"somestate"}],
 "platform 6"=>[{:pkg=>"package6", :state=>"somestate"}]}

通常,这将是所需的输出。


第 3 步:您似乎需要输出,其中代表平台的每个键值对都存在于自己的数组中。我们需要这一步来将第 2 步的哈希转换为所需的输出。

output = h.map {|k,v| [{k => v}]}

此时output的值如下图所示:

[[{"platform 5"=>
    [{:pkg=>"package1", :state=>"somestate"},
     {:pkg=>"package3", :state=>"somestate"},
     {:pkg=>"package4", :state=>"somestate"}]}],
 [{"platform 7"=>
    [{:pkg=>"package2", :state=>"somestate"},
     {:pkg=>"package5", :state=>"somestate"}]}],
 [{"platform 6"=>[{:pkg=>"package6", :state=>"somestate"}]}]]

附注

要漂亮地打印哈希和数组,您可以使用 Ruby 的PP class。例如

require "pp

pp hash_object

【讨论】:

  • 也许each_with_object 而不是reduce 来摆脱那个讨厌的; memo
【解决方案2】:

您可以使用group_by。这里:

aff_packages.group_by { |a| a[:platform] }
# => {"platform 5"=>[{:platform=>"platform 5", :pkg=>"package1", :state=>"somestate"}, {:platform=>"platform 5", :pkg=>"package3", :state=>"somestate"}, {:platform=>"platform 5", :pkg=>"package4", :state=>"somestate"}],
# "platform 7"=>[{:platform=>"platform 7", :pkg=>"package2", :state=>"somestate"}, {:platform=>"platform 7", :pkg=>"package5", :state=>"somestate"}],
# "platform 6"=>[{:platform=>"platform 6", :pkg=>"package6", :state=>"somestate"}]}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-26
    相关资源
    最近更新 更多