Ruby 如何以这种方式合并散列

Ruby 如何以这种方式合并散列,ruby,hash,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

我写了一个巨大的代码,如下所示

 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"]}}

我不知道如何用这种方式合并,有人能帮我吗

一般来说,在处理底层数据对象时,最好建立所需的数据结构。但是,如果以后需要转换散列,有一种方法:

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"]}}

我希望您会觉得这很有用。

一般来说,在处理底层数据对象时,构建所需的数据结构可能是一个好主意。但是,如果以后需要转换散列,有一种方法:

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"]}}

我希望你觉得这很有用。

如果我知道你想要这样的东西

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}
这是一个通用的解决方案,您可以进一步删除不需要的关键广告适用于满足您的需要

编辑-收集评论 删除不需要的关键点和简化的合并块:

keys_to_remove = ["id=lastName", "whatever", nil]
test_1_value = my_hash['Test1'].merge(my_hash['Action']) { |k, *vs| vs }.delete_if{ |k, _| keys_to_remove.include? k }
# => {"css=#entityType"=>["Individual", "Type"], "id=idNumber"=>["2323", "TypeAndWait"], "id=shortName"=>["M", "TypeAndTab"], "id=FirstName"=>["Abc", "TypeTabAndWait"]}

如果我知道你想要这样的东西

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}
这是一个通用的解决方案,您可以进一步删除不需要的关键广告适用于满足您的需要

编辑-收集评论 删除不需要的关键点和简化的合并块:

keys_to_remove = ["id=lastName", "whatever", nil]
test_1_value = my_hash['Test1'].merge(my_hash['Action']) { |k, *vs| vs }.delete_if{ |k, _| keys_to_remove.include? k }
# => {"css=#entityType"=>["Individual", "Type"], "id=idNumber"=>["2323", "TypeAndWait"], "id=shortName"=>["M", "TypeAndTab"], "id=FirstName"=>["Abc", "TypeTabAndWait"]}
我想进一步说明。虽然答案描述了问题应该如何解决,但它没有使用任何迭代。您可以通过以下方式迭代测试:

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'
值合并请记住,这种方法会变异
散列
变量。如果你不想这样做,你应该事先简单地进行散列,或者寻找一种非变异的方法。

优化

如果您使用Ruby 2.5.0或更高版本,则可以使用代替

如果100%确定
tests
中的每个
test
都包含相同的键,并且始终至少存在一个测试,则可以将
action_和_test_键
分配移出
#每个_值
块以节省资源

tests = hash # anchor point in the above solution
action_with_test_keys = action.slice(*tests.values.first.keys) # added
参考资料

  • 散列
    变量中删除
    'Action'
  • 迭代
    测试的每个值
  • 只选择
    测试中出现的
    操作
  • 检查给定的密钥是否存在
  • action\u与\u test\u键合并,并更新
    test
    变量
  • 替换
    Hash#如果使用Ruby 2.5.0或更高版本,请选择
我想继续。虽然答案描述了问题应该如何解决,但它没有使用任何迭代。您可以通过以下方式迭代测试:

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'
值合并请记住,这种方法会变异
散列
变量。如果你不想这样做,你应该事先简单地进行散列,或者寻找一种非变异的方法。

优化

如果您使用Ruby 2.5.0或更高版本,则可以使用代替

如果100%确定
tests
中的每个
test
都包含相同的键,并且始终至少存在一个测试,则可以将
action_和_test_键
分配移出
#每个_值
块以节省资源

tests = hash # anchor point in the above solution
action_with_test_keys = action.slice(*tests.values.first.keys) # added
参考资料

  • 散列
    变量中删除
    'Action'
  • 迭代
    测试的每个值
  • 只选择
    测试中出现的
    操作
  • 检查给定的密钥是否存在
  • action\u与\u test\u键合并,并更新
    test
    变量
  • 替换
    Hash#如果使用Ruby 2.5.0或更高版本,请选择

是否要操纵第一个哈希以获取第二个哈希?我想您需要转义逗号:
“id=\“lastName=>”Gg“
或使用
是的,我需要将所显示的同一个键的值进行组合。我不确定这是否是您的意图,但名称用法表明您的代码中存在缺陷。如果使用
*数据行
压缩
标题
,则输出将为列。这意味着映射中的变量名称不应该是
数据行
,而应该是
。此列的标题作为第一个元素。通过执行
local[1..-1].map
您将循环遍历除第一列以外的所有列。您好,这是代码的一部分,因为这里不需要这样做,所以我添加了一部分。如果你想看到完整的代码,我明天会添加。@Rajagopalan没有必要添加完整的代码(这会使问题变得混乱),我只是想确保你的方法是有意的。你想操纵第一个哈希来获得第二个吗?我想您需要转义逗号:
“id=\“lastName=>”Gg“
或使用
是的,我需要将所显示的同一个键的值进行组合。我不确定这是否是您的意图,但名称用法表明您的代码中存在缺陷。如果使用
*数据行
压缩
标题
,则输出将为列。这意味着映射中的变量名称不应该是
数据行
,而应该是
。此列的标题作为第一个元素。通过执行
local[1..-1].map
您将循环遍历除第一列以外的所有列。您好,这是代码的一部分,因为这里不需要这样做,所以我添加了一部分。如果你想看完整的代码,我将在明天添加。@Rajagop