2017-04-11 21 views
-4
更新值

考慮變量:同時讀取多個哈希和紅寶石

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,如果散列值中的最後一個字符與散列h2中的某個鍵匹配,則將該值替換爲相應的值並將符號前綴替換爲字符串。

例如:其中5從屬於並且當我們掃描散列h1,對於值「10000100126N」,因爲最後一個字符是N和它在h2存在,則輸出應該是「-100001001265」 - 被前置。 [不是說ctr是'cobol']

但是,如果我們看第二個值「CDE」=>「2013-08-30-}」,因爲對於這個鍵值對,ctr值是不是cobol,凌晨與絃樂無關。

這是我迄今所做的:

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'

+1

你的問題是什麼? – sawa

+0

@sawa - 如果數組'ctr'中的值爲'cobol',那麼需要轉換散列'h1'中對應元素的值(索引明)。 例如,數組ctr中的cobol的索引是[0,5] 0和散列h1中的5個元素是'ABC'和'OPP',散列中的相應值應根據以下邏輯: 如果散列h1中的值的最後一個字符存在於散列h2中,則將其替換爲散列h2中對應的鍵值[最後一個字符],例如:10000100126N應改爲-100001001265 我需要實現上述。 –

回答

2

首先,當您匹配Hash職位與Array索引時發出警告。在您的示例中,['cobol',nil,nil,'test',nil,'cobol', nil]h1的內部Hash中的密鑰["ABC", "CDE", "TPP", "APD", "PRODUCTID", "OPP", "CTC"]相對應。請記住,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"}} 

正如你可以看到我使用zipHash的每個值與ctrArray結合起來。我也在使用批量分配(不知道正確的術語)。這方面的一個簡單的例子是:

(v1, v2, v3) = [1, 2, 3] 

從而造成v1具有值1,具有值2v2。在第二個map中有2個參數,第一個是Array,其中包含內部密鑰和值Hash,第二個是來自合併的ctrArray的值。通過使用質量分配,我可以給出鍵和值他們自己的變量名。

由於邏輯對於單線程來說有點多餘,所以我將它移動到lambda上,但這也可以是一個函數(當將h2作爲參數傳遞時)。

1

你試圖匹配一個數組和一個哈希,這隻會導致你的問題。如果你改變ctr到哈希以及它會更容易:

ctr = {"ABC" => "cobol", "CDE" => nil, "TPP" => nil, "APD" => "test", "PRODUCTID" => nil, "OPP" => "cobol", "CTC" => nil} 

那麼,你至少可以通過密鑰匹配。

更好的是開始創建一個對象而不是使用你的散列。一旦你開始嵌套集合對象這個深處,是時候創建一些對象來讓你的生活更輕鬆。

+0

我忘了提及物體。很高興在這裏見到他們。 –