考虑变量:
ctr = ['cobol',nil,nil,'test',nil,'cobol', nil]
h1 = {
0=>{"ABC"=>"10000100126N", "CDE"=>"2013-08-30-}", "TPP"=>"11400000206633458812N", "APD"=> "01531915972", "PRODUCTID"=>"113n", "OPP"=>"201509n", "CTC"=>"C"},
1=>{"ABC"=>"00000039540A", "CDE"=>"0182.22X", "TPP"=>"1234.565N", "APD"=>"12345600", "PRODUCTID"=>"ACHN", "OPP"=>"00000000000119964.1256", "CTC"=>"00000000000211920"}
}
h2 = {'{' => '+0', 'A' => '+1', 'B' => '+2', '}' => '-0', 'N' => '-5'}
任务是读取ctr
数据,其值为cobol
,我们需要在h1哈希中为这些值应用逻辑。
我们需要解析散列h1
,如果散列值中的最后一个char与散列h2
中的一个键匹配,则将该值替换为相应的值,并将前缀符号替换为该字符串。
例如:当我们扫描散列h1
时,对于值“10000100126N”,因为最后一个char是N并且它存在于h2
中,那么输出应该是'-100001001265',其中5是附加和 - 前置。 [不是说这是'cobol'的中心]
但是如果我们看第二个值“CDE”=&gt;“2013-08-30-}”,因为对于这个键值对,ctr值不是cobol,我们不对字符串做任何事情。< / p>
这是我到目前为止所做的:
h1.each do |k,h|
h.update(h) do |*, v|
# puts v
h2.each do |q,p|
if (v[-1] == q)
v.sub!(v[-1], p[-1])
v.sub!(/(.*?)/, p[0] +'\1')
end
end
v
end
end
此代码正在根据需求更新字符串,但是它运行h1
中的所有值,我只需要为数组ctr
中的值的相应索引运行代码是'cobol'
答案 0 :(得分:2)
首先,当您将Hash
个位置与Array
个索引匹配时会发出警告。在您的示例中,['cobol',nil,nil,'test',nil,'cobol', nil]
与来自["ABC", "CDE", "TPP", "APD", "PRODUCTID", "OPP", "CTC"]
的内部Hash
的密钥h1
相对应。请记住,Hash
不是基于索引的,而是基于密钥的。这意味着,理论上不保持散列的顺序。更好的方法是定义Hash
,如下所示:{"ABC"=>"cobol", "CDE"=>nil, "TPP"=>nil, "APD"=>"test", "PRODUCTID"=>nil, "OPP"=>"cobol", "CTC"=>nil}
。
有了这个警告,让我们回答。
您要找的是Enumerable#zip
函数,用于将每个值与ctr
中的相应值组合。
[:a, :b, :c].zip([1, 2, 3])
#=> [[:a, 1], [:b, 2], [:c, 3]]
首先我们需要遍历您的哈希,您正在使用Hash#each
。由于这是转换Enumerable#map
更适合。 map
函数生成具有转换值的数组。生成的数组可以转换回具有正确结构的Hash
。
[[:a, 1], [:b, 2], [:c, 3]].to_h
#=> {:a => 1, :b => 2, :c => 3}
这是我提出的解决方案。它不是最干净的,但它有效。
check_logic = lambda do |type, value|
return value unless type == 'cobol'
return value unless h2.has_key?(value[-1])
"#{h2[value[-1]][0]}#{value[0...-1]}#{h2[value[-1]][-1]}"
end
result = h1.map { |k1, v1| [k1, v1.zip(ctr).map { |(k2, v2), type| [k2, check_logic.call(type, v2)] }.to_h] }.to_h
#=> {0=>{"ABC"=>"-100001001265", "CDE"=>"2013-08-30-}", "TPP"=>"11400000206633458812N", "APD"=>"01531915972", "PRODUCTID"=>"113n", "OPP"=>"201509n", "CTC"=>"C"}, 1=>{"ABC"=>"+000000395401", "CDE"=>"0182.22X", "TPP"=>"1234.565N", "APD"=>"12345600", "PRODUCTID"=>"ACHN", "OPP"=>"00000000000119964.1256", "CTC"=>"00000000000211920"}}
正如您所看到的,我正在使用zip
将Hash
的每个值与ctr
Array
结合起来。我也在使用群发作业(不知道正确的术语)。一个简单的例子是:
(v1, v2, v3) = [1, 2, 3]
导致v1
的值1
,v2
的值为2
。在第二个map
中有2个参数,第一个是Array
,包含内部Hash
的键和值,第二个是合并ctr
的值Array
。通过使用质量赋值,我可以给出键和值自己的变量名。
由于逻辑对于一个衬管来说有点太多,我将它移动到lambda,但这也可以是一个函数(当将h2作为param传递时)。
答案 1 :(得分:1)
您正在尝试匹配数组和哈希,这只会导致您遇到问题。如果您将ctr
更改为哈希值会更容易:
ctr = {"ABC" => "cobol", "CDE" => nil, "TPP" => nil, "APD" => "test", "PRODUCTID" => nil, "OPP" => "cobol", "CTC" => nil}
然后至少你可以按键匹配。
更好的方法是开始创建对象而不是使用哈希。一旦你开始嵌套集合对象,就可以创建某种对象来让你的生活更轻松。