2017-08-13 47 views
0

從不同陣列的散列的創建與元素散在訓練營練習中,我們在獲得這個數組:紅寶石

library = [ 
    { 
    "title" => "Hitchhiker's Guide", 
    "Author" => "Douglas Adams", 
    "categories" => [ "comedy", "fiction", "british"] 
    }, 
    { 
    "title" => "Pride and Prejudice", 
    "Author" => "Jane Austen", 
    "categories" => [ "morality", "fiction", "society", "british"] 
    }, 
    { 
    "title" => "Search Inside Yourself", 
    "Author" => "Chade-Meng Tan", 
    "categories" => [ "self improvement", "non-fiction", "mindfulness", "business"] 
    }, 
    { 
    "title" => "Benjamin Franklin: An American Life", 
    "Author" => "Walter Isaacson", 
    "categories" => [ "non-fiction", "history", "founding fathers"] 
    }, 
    { 
    "title" => "Glengarry Glen Ross", 
    "Author" => "David Mamet", 
    "categories" => [ "play", "fiction", "drama"] 
    } 
] 

,我們需要與類別爲元素的新哈希值,和標題作爲價值。

能夠弄清楚如何製作category_hash,但我無法弄清楚如何將標題附加到每個類別。這裏是我的代碼:

category_hash = {} 
sub_category = [] 

library.each do |book| 
    book["categories"].each do |category| 
    sub_category << category 
    end 
    sub_category.each do |index| 
    category_hash[index] = "I'm not sure how to append the titles here" 
    end 
end 

p category_hash 

有人可以幫我弄清楚這一步嗎?

+0

您需要澄清(與編輯)你的意思是「...與類別作爲元素...」。首先,你的意思是「鑰匙」而不是「元素」。你會看到並非所有答案都以相同的方式解釋。迄今爲止,一個答案假設「類別」是與「庫」的元素(散列)中的鍵「類別」相關聯的值;兩個答案假定「類別」是包含在「圖書館」元素(「喜劇」,「小說」,「英國」,「道德」,「社會」等)中的一個或多個「類別」 。我猜你的意圖是後一種解釋。 –

回答

2

您可以使用Enumerable#each_with_object

library.each_with_object({}) do |hash, result| 
    result[hash['categories']] = hash['title'] 
end 
# { 
# ["comedy", "fiction", "british"]=>"Hitchhiker's Guide", 
# ["morality", "fiction", "society", "british"]=>"Pride and Prejudice", 
# ["self improvement", "non-fiction", "mindfulness", "business"]=>"Search Inside Yourself", 
# ["non-fiction", "history", "founding fathers"]=>"Benjamin Franklin: An American Life", 
# ["play", "fiction", "drama"]=>"Glengarry Glen Ross" 
# } 
+0

假設另一個散列被添加到'librar',其中包含鍵值對''categories「=> [」喜劇「,」小說「,」英國「]'。然後怎樣呢?看到我對這個問題的評論。 –

1

這裏是另一種方式來做到這一點,這是比@ AndreyDeineko的回答效率較低。

library.map{|h| h.values_at("categories", "title")}.to_h 

結果:

{ 
    ["comedy", "fiction", "british"]=>"Hitchhiker's Guide", 
    ["morality", "fiction", "society", "british"]=>"Pride and Prejudice", 
    ["self improvement", "non-fiction", "mindfulness", "business"]=>"Search Inside Yourself", 
    ["non-fiction", "history", "founding fathers"]=>"Benjamin Franklin: An American Life", 
    ["play", "fiction", "drama"]=>"Glengarry Glen Ross" 
} 

在你想讓它由"category"屬性(其中,當然,將取決於陣列中的散列項目的順序進行分配的情況下,我認爲你的意思是以後一個在較早的一個優先):

library.each_with_object({}) do 
    |h, result| h["categories"].each_with_object(result) do 
    |k, result| result[k] = h["title"] 
    end 
end 

結果:

{ 
    "comedy"=>"Hitchhiker's Guide", 
    "fiction"=>"Glengarry Glen Ross", 
    "british"=>"Pride and Prejudice", 
    "morality"=>"Pride and Prejudice", 
    "society"=>"Pride and Prejudice", 
    "self improvement"=>"Search Inside Yourself", 
    "non-fiction"=>"Benjamin Franklin: An American Life", 
    "mindfulness"=>"Search Inside Yourself", 
    "business"=>"Search Inside Yourself", 
    "history"=>"Benjamin Franklin: An American Life", 
    "founding fathers"=>"Benjamin Franklin: An American Life", 
    "play"=>"Glengarry Glen Ross", 
    "drama"=>"Glengarry Glen Ross" 
} 
1

如果您需要某個類別中的每本書的列表以及出現在多個類別中的書籍,則可以在您將initialize the Hash設置爲將所有未知鍵設置爲包含數組的值時附加default_proc。然後,你只需遍歷每本書在圖書館和增加它的標題的列表中每個類別是在:

# Pass the category hash a default proc, which will be called 
# whenever a key it doesn't have is accessed. So, when you 
# encounter a brand new category, it'll already be set up with 
# an array 
category_hash = Hash.new { |hash, key| hash[key] = [] } 
library.each do |book| 
    book['categories'].each do |category| 
    # since we passed the default, no worrying, an array will be 
    # there and we can just add our value into it 
    category_hash[category] << book['title'] 
    end 
end 

puts category_hash 

結果:

{ 
    "comedy"=>["Hitchhiker's Guide"], 
    "fiction"=>["Hitchhiker's Guide", "Pride and Prejudice", "Glengarry Glen Ross"], 
    "british"=>["Hitchhiker's Guide", "Pride and Prejudice"], 
    "morality"=>["Pride and Prejudice"], 
    "society"=>["Pride and Prejudice"], 
    "self improvement"=>["Search Inside Yourself"], 
    "non-fiction"=>["Search Inside Yourself", "Benjamin Franklin: An American Life"], 
    "mindfulness"=>["Search Inside Yourself"], 
    "business"=>["Search Inside Yourself"], 
    "history"=>["Benjamin Franklin: An American Life"], 
    "founding fathers"=>["Benjamin Franklin: An American Life"], 
    "play"=>["Glengarry Glen Ross"], 
    "drama"=>["Glengarry Glen Ross"] 
} 

還有each_with_object所以你可以修改這

result = library.each.with_object(Hash.new { |hash, key| hash[key] = [] }) do |book, category_hash| 
    book['categories'].each do |category| 
    # since we passed the default, no worrying, an array will be 
    # there and we can just add our value into it 
    category_hash[category] << book['title'] 
    end 
end 
puts result 

這將返回category_hash,並保存最後一行代碼:

puts(library.each.with_object(Hash.new { |hash, key| hash[key] = [] }) do |book, category_hash| 
    book['categories'].each do |category| 
    # since we passed the default, no worrying, an array will be 
    # there and we can just add our value into it 
    category_hash[category] << book['title'] 
    end 
end) 
1

這是其他答案的輕微變體。

library = [ 
    {title: "Hitch Guide", by: "Doug", cats: ["comedy", "fiction", "british"]}, 
    {title: "P and P",  by: "Jane", cats: ["morality", "fiction", "british"]}, 
    {title: "Searchin'", by: "Chad", cats: ["non-fiction", "morality", "gps"]}, 
    {title: "Crazy Ben", by: "Walt", cats: ["non-fiction", "comedy", "dads"]} 
] 
    # => [{:title=>"Hitch Guide", :by=>"Doug", :cats=>["comedy", "fiction", "british"]}, 
    #  {:title=>"P and P", :by=>"Jane", :cats=>["morality", "fiction", "british"]}, 
    #  {:title=>"Searchin'", :by=>"Chad", :cats=>["non-fiction", "morality", "gps"]}, 
    #  {:title=>"Crazy Ben", :by=>"Walt", :cats=>["non-fiction", "comedy", "dads"]}] 

library.each_with_object({}) do |g,h| 
    title = g[:title] 
    g[:cats].each { |c| (h[c] ||= []) << title } 
end 
    #=> {"comedy"=>["Hitch Guide", "Crazy Ben"], 
    # "fiction"=>["Hitch Guide", "P and P"], 
    # "british"=>["Hitch Guide", "P and P"], 
    # "morality"=>["P and P", "Searchin'"], 
    # "non-fiction"=>["Searchin'", "Crazy Ben"], 
    # "gps"=>["Searchin'"], 
    # "dads"=>["Crazy Ben"]}