如何以这种方式合并哈希

时间:2018-08-27 14:54:49

标签: ruby hash

我在下面写了一个巨大的代码

 headers, *data_rows = @testCaseSheet
    local = headers.zip(*data_rows)
    local = local[1..-1].map {|dataRow| local[0].zip(dataRow).to_h}
    testCaseHash = {}
    local.each do |value|
      testCaseHash[value["Locator"]] = value.tap {|hs| hs.delete("Locator")}
    end
    @testCaseSheet = []
    p testCaseHash
    [h["Test Name"], testCaseHash],

如下所示,现在我需要将此操作与每个测试合并,我不知道该怎么做。

hash= {"Action"=>{"css=#entityType"=>"Type", "id=idNumber"=>"TypeAndWait", "id=shortName"=>"TypeAndTab", "id=FirstName"=>"TypeTabAndWait", nil=>nil}, 

"Test1"=>{"css=#entityType"=>"Individual", "id=idNumber"=>"2323", "id=shortName"=>"M", "id=FirstName"=>"Abc", "id=lastName"=>"Gg"}, 

"Test2"=>{"css=#entityType"=>"Legal", "id=idNumber"=>"2323", "id=shortName"=>"Z", "id=FirstName"=>"Xyz", "id=lastName"=>"Gg"}}

现在,我想将此操作与以下测试进行合并,

hash= { "Test1"=>{"css=#entityType"=>["Individual","Type"], "id=idNumber"=>["2323","TypeAndWait"], "id=shortName"=>["M","TypeAndTab"], "id=FirstName"=>["Abc","TypeTabAndWait"]}, 

"Test2"=>{"css=#entityType"=>["Legal""Type"], "id=idNumber"=>["2323","TypeAndWait"], "id=shortName"=>["Z","TypeAndTab"], "id=FirstName"=>["Xyz","TypeTabAndWait"]}}

我不知道如何合并,有人可以帮助我吗?

3 个答案:

答案 0 :(得分:2)

通常来说,在处理底层数据对象的同时建立所需的数据结构可能是一个好主意。但是,如果您之后需要转换哈希,可以采用以下一种方法:

hash = {
    "Action"=>{"css=#entityType"=>"Type", "id=idNumber"=>"TypeAndWait", "id=shortName"=>"TypeAndTab", "id=FirstName"=>"TypeTabAndWait", nil=>nil}, 
    "Test1"=>{"css=#entityType"=>"Individual", "id=idNumber"=>"2323", "id=shortName"=>"M", "id=FirstName"=>"Abc", "id=lastName"=>"Gg"}, 
    "Test2"=>{"css=#entityType"=>"Legal", "id=idNumber"=>"2323", "id=shortName"=>"Z", "id=FirstName"=>"Xyz", "id=lastName"=>"Gg"}
  }

action = hash['Action']
tests = hash.reject { |k, v| k == 'Action' }


mapping = tests.map do |name, test|
  groups = (action.to_a + test.to_a).group_by(&:first)
  no_keys = groups.map { |k, v| [k, v.each(&:shift).flatten] }
  no_keys.reject! { |k, v| v.length == 1 }
  [name, Hash[no_keys]]
end

Hash[mapping]
#  => {"Test1"=>{"css=#entityType"=>["Type", "Individual"], "id=idNumber"=>["TypeAndWait", "2323"], "id=shortName"=>["TypeAndTab", "M"], "id=FirstName"=>["TypeTabAndWait", "Abc"]},
#      "Test2"=>{"css=#entityType"=>["Type", "Legal"], "id=idNumber"=>["TypeAndWait", "2323"], "id=shortName"=>["TypeAndTab", "Z"], "id=FirstName"=>["TypeTabAndWait", "Xyz"]}}

希望您会觉得有用。

答案 1 :(得分:2)

如果我了解您想要这样的东西

Traceback (most recent call last):
  File "so.py", line 3, in <module>
    my_pet = Animal()
  File "/home/wdwickar/pyside/animal.py", line 4, in __init__
    self.action = {'feed':feed_pet}
NameError: name 'feed_pet' is not defined

您的情况可以是:

hash_1 = {a: "a1", b: "b1", c: "c1"}
hash_2 = {a: "a2", b: "b2", d: "d1"}

p hash_1.merge(hash_2) { |k, v1, v2| v1 = [v1, v2] }
# => {:a=>["a1", "a2"], :b=>["b1", "b2"], :c=>"c1", :d=>"d1"}

这是一个通用的解决方案,您可以进一步进行操作,以移除适合您需求的不需要的按键。

编辑-收集评论

删除不需要的键和简化的合并块:

test_1_value = my_hash['Test1'].merge(my_hash['Action']) { |k, v1, v2| v1 = [v1, v2] }

# => {"css=#entityType"=>["Individual", "Type"], "id=idNumber"=>["2323", "TypeAndWait"], "id=shortName"=>["M", "TypeAndTab"], "id=FirstName"=>["Abc", "TypeTabAndWait"], "id=\"lastName"=>"Gg", nil=>nil}

答案 2 :(得分:2)

我想在iGians answer上展开。尽管答案描述了应如何解决该问题,但它没有使用任何迭代。您可以通过以下方式遍历测试:

hash = {
  "Action"=>{"css=#entityType"=>"Type", "id=idNumber"=>"TypeAndWait", "id=shortName"=>"TypeAndTab", "id=FirstName"=>"TypeTabAndWait", nil=>nil}, 
  "Test1"=>{"css=#entityType"=>"Individual", "id=idNumber"=>"2323", "id=shortName"=>"M", "id=FirstName"=>"Abc", "id=lastName"=>"Gg"}, 
  "Test2"=>{"css=#entityType"=>"Legal", "id=idNumber"=>"2323", "id=shortName"=>"Z", "id=FirstName"=>"Xyz", "id=lastName"=>"Gg"},
}

action = hash.delete 'Action'
tests = hash

tests.each_value do |test|
  action_with_test_keys = action.select { |key, _value| test.key? key }
  test.merge!(action_with_test_keys) { |_key, *values| values } # values = [old, new]
end

这假定'Action'是哈希中唯一的非测试键,并且所有其他值都应与'Action'值合并。 请记住,这种方法会突变hash变量。如果您不希望这样做,则应该事先#dup进行哈希处理,或者寻找一种不变异的方法。

优化

如果您使用的是Ruby 2.5.0或更高版本,则可以使用#slice代替#select

action.select { |key, _value| test.key? key }
# is replaced with
action.slice(*test.keys)

如果您100%确保test中的每个tests都包含相同的键,并且始终存在至少一个测试,则可以将action_with_test_keys分配移出{ {1}}块以节省资源。

#each_value

参考

  • Hash#deletetests = hash # anchor point in the above solution action_with_test_keys = action.slice(*tests.values.first.keys) # added 变量中删除'Action'键。
  • Hash#each_value遍历hash的每个值。
  • Hash#select仅选择tests上的action键。
  • Hash#key?检查给定密钥是否存在。
  • Hash#merge!合并test并更新action_with_test_keys变量。
  • 如果您使用的是Ruby 2.5.0或更高版本,请用
  • Hash#slice代替test