2016-12-08 238 views
6

我有一個哈希:多個子哈希出一個哈希

hash = {"a_1_a" => "1", "a_1_b" => "2", "a_1_c" => "3", "a_2_a" => "3", 
     "a_2_b" => "4", "a_2_c" => "4"} 

什麼讓下面的子哈希值的最佳方式:

[{"a_1_a" => "1", "a_1_b" => "2", "a_1_c" => "3"}, 
{"a_2_a" => "3", "a_2_b" => "4", "a_2_c" => "4"}] 

我希望他們通過密鑰分組,基於正則表達式/^a_(\d+)/。如果有人有任何建議,我會在原始散列中使用50個以上的鍵/值對,所以動態變化最好。

+3

這樣的快速選擇提供了可能阻礙其他的答案和短路那些答案仍在工作的第一個答案的。沒有急於。在選擇答案之前,許多人至少要等上幾個小時,有些人的等待時間要長得多。 –

+1

好的,謝謝你的建議,我是新來的:) –

+0

其實有些人等了好幾個月!別人從來沒有做過LOL –

回答

7

如果你只關心中間組件,您可以使用group_by讓你最那裏的方式:

hash.group_by do |k,v| 
    k.split('_')[1] 
end.values.map do |list| 
    Hash[list] 
end 

# => [{"a_1_a"=>"1", "a_1_b"=>"2", "a_1_c"=>"3"}, {"a_2_a"=>"3", "a_2_b"=>"4", "a_2_c"=>"4"}] 

的最後一步是提取分組名單,並結合這些回所需的散列。

+1

這看起來像OP正在尋找什麼。如果OP對這種事情感興趣,也可以使它更簡潔 'hash.group_by {| k,_ | k.split('_')[1]} .values.map(&:to_h)' – Damon

+0

正是我在找的東西,謝謝! –

4

代碼

def partition_hash(hash) 
    hash.each_with_object({}) do |(k,v), h| 
    key = k[/(?<=_).+(?=_)/] 
    h[key] = (h[key] || {}).merge(k=>v) 
    end.values 
end 

hash = {"a_1_a"=>"1", "a_1_b"=>"2", "a_1_c"=>"3", "a_2_a"=>"3", "a_2_b"=>"4", "a_2_c"=>"4"} 
partition_hash(hash) 
    #=> [{"a_1_a"=>"1", "a_1_b"=>"2", "a_1_c"=>"3"}, 
    # {"a_2_a"=>"3", "a_2_b"=>"4", "a_2_c"=>"4"}] 

說明

的步驟如下。

enum = hash.each_with_object({}) 
    #=> #<Enumerator: {"a_1_a"=>"1", "a_1_b"=>"2", "a_1_c"=>"3", "a_2_a"=>"3", 
    #     "a_2_b"=>"4", "a_2_c"=>"4"}:each_with_object({})> 

此枚舉的第一元素時產生並傳遞給塊,和塊變量使用並行分配計算。

(k,v), h = enum.next 
    #=> [["a_1_a", "1"], {}] 
k #=> "a_1_a" 
v #=> "1" 
h #=> {} 

並且執行塊計算。

key = k[/(?<=_).+(?=_)/] 
    #=> "1" 
h[key] = (h[key] || {}).merge(k=>v) 
    #=> h["1"] = (h["1"] || {}).merge("a_1_a"=>"1") 
    #=> h["1"] = (nil || {}).merge("a_1_a"=>"1") 
    #=> h["1"] = {}.merge("a_1_a"=>"1") 
    #=> h["1"] = {"a_1_a"=>"1"} 

所以現在

h #=> {"1"=>{"a_1_a"=>"1"}} 

現在產生的enum的下一個值,並傳遞給塊,並且執行下面的計算。

(k,v), h = enum.next 
    #=> [["a_1_b", "2"], {"1"=>{"a_1_a"=>"1"}}] 
k #=> "a_1_b" 
v #=> "2" 
h #=> {"1"=>{"a_1_a"=>"1"}} 

key = k[/(?<=_).+(?=_)/] 
    #=> "1" 
h[key] = (h[key] || {}).merge(k=>v) 
    #=> h["1"] = (h["1"] || {}).merge("a_1_b"=>"2") 
    #=> h["1"] = ({"a_1_a"=>"1"}} || {}).merge("a_1_b"=>"2") 
    #=> h["1"] = {"a_1_a"=>"1"}}.merge("a_1_b"=>"2") 
    #=> h["1"] = {"a_1_a"=>"1", "a_1_b"=>"2"} 

enum其餘四個元件之後已被通過以下面已經返回塊。

h #=> {"1"=>{"a_1_a"=>"1", "a_1_b"=>"2", "a_1_c"=>"3"}, 
    # "2"=>{"a_2_a"=>"3", "a_2_b"=>"4", "a_2_c"=>"4"}} 

最後一步是簡單地提取值。

h.values 
    #=> [{"a_1_a"=>"1", "a_1_b"=>"2", "a_1_c"=>"3"}, 
    # {"a_2_a"=>"3", "a_2_b"=>"4", "a_2_c"=>"4"}]