2017-09-21 1 views
1

Je suis nouveau à rubis, je suis en train de résoudre un problème qui implique des hachages et des clés. Le problème me demande d'implémenter une méthode, #pet_types, qui accepte un hachage comme argument. Le hachage utilise les # noms des personnes comme clés, et les valeurs sont des tableaux de types d'animaux de compagnie que la personne possède. Ma question est d'utiliser Hash # chaque méthode pour itérer à travers chaque num à l'intérieur du tableau. Je me demandais s'il y avait une différence entre résoudre le problème en utilisant hash # each ou hash.sort.each? J'ai passé plusieurs heures à trouver une solution différente et encore à comprendre quelles sont les différentes approches entre les deux façons de résoudre le problème ci-dessous.Questions sur la mise en œuvre des hachages dans ruby ​​

j'inclure mon code dans repl.it: https://repl.it/H0xp/6 ou vous pouvez voir ci-dessous:

# Pet Types 
# ------------------------------------------------------------------------------ 
# Implement a method, #pet_types, that accepts a hash as an argument. The hash uses people's 
# names as keys, and the values are arrays of pet types that the person owns. 

# Example input: 
# { 
# "yi" => ["dog", "cat"], 
# "cai" => ["dog", "cat", "mouse"], 
# "venus" => ["mouse", "pterodactyl", "chinchilla", "cat"] 
# } 
def pet_types(owners_hash) 

    results = Hash.new {|h, k| h[k] = [ ] } 
    owners_hash.sort.each { |k, v| v.each { |pet| results[pet] << k } } 
    results 
end 

puts "-------Pet Types-------" 

owners_1 = { 
    "yi" => ["cat"] 
} 
output_1 = { 
    "cat" => ["yi"] 
} 

owners_2 = { 
    "yi" => ["cat", "dog"] 
} 
output_2 = { 
    "cat" => ["yi"], 
    "dog" => ["yi"] 
} 

owners_3 = { 
    "yi" => ["dog", "cat"], 
    "cai" => ["dog", "cat", "mouse"], 
    "venus" => ["mouse", "pterodactyl", "chinchilla", "cat"] 
} 
output_3 = { 
    "dog" => ["cai", "yi"], 
    "cat" => ["cai", "venus", "yi"], 
    "mouse" => ["cai", "venus"], 
    "pterodactyl" => ["venus"], 
    "chinchilla" => ["venus"] 
} 


    # method 2 
    # The 2nd and 3rd method should return a hash that uses the pet types as keys and the values should 
    # be a list of the people that own that pet type. The names in the output hash should 
    # be sorted alphabetically 

    # switched_hash = Hash.new() 

    # owners_hash.each do |owner, pets_array| 
    # pets_array.each do |pet| 
    #  select_owners = owners_hash.select { |owner, pets_array| 

owners_hash[owner].include?(pet) } 

    #  switched_hash[pet] = select_owners.keys.sort 
    # end 
    # end 

    # method 3 
    #switched_hash 
    # pets = Hash.new {|h, k| h[k] = [ ] } # WORKS SAME AS: pets = Hash.new(Array.new) 
    # owners = owners_hash.keys.sort 
    # owners.each do |owner| 
    # owners_hash[owner].each do |pet| 
    #  pets[pet] << owner 
    # end 
    # end 
    # pets 
# Example output: 

# output_3 = { 
# "dog" => ["cai", "yi"], 
# "cat" => ["cai", "venus", "yi"], ---> (sorted alphabetically!) 
# "mouse" => ["cai", "venus"], 
# "pterodactyl" => ["venus"], 
# "chinchilla" => ["venus"] 
# } 

J'utilise une structure de données de hachage dans mon programme d'abord résoudre ce problème. Puis j'ai essayé de le réécrire en utilisant le pet_hash. Et mes codes final est le suivant:

def pet_types(owners_hash) 
    pets_hash = Hash.new { |k, v| v = [] } 

    owners_hash.each do |owner, pets| 
    pets.each do |pet| 
     pets_hash[pet] += [owner] 
    end 
    end 


    pets_hash.values.each(&:sort!) 

    pets_hash 
end 

puts "-------Pet Types-------" 
owners_1 = { 
    "yi" => ["cat"] 
} 
output_1 = { 
    "cat" => ["yi"] 
} 
owners_2 = { 
    "yi" => ["cat", "dog"] 
} 
output_2 = { 
    "cat" => ["yi"], 
    "dog" => ["yi"] 
} 
owners_3 = { 
    "yi" => ["dog", "cat"], 
    "cai" => ["dog", "cat", "mouse"], 
    "venus" => ["mouse", "pterodactyl", "chinchilla", "cat"] 
} 
output_3 = { 
    "dog" => ["cai", "yi"], 
    "cat" => ["cai", "venus", "yi"], 
    "mouse" => ["cai", "venus"], 
    "pterodactyl" => ["venus"], 
    "chinchilla" => ["venus"] 
} 
puts pet_types(owners_1) == output_1 
puts pet_types(owners_2) == output_2 
puts pet_types(owners_3) == output_3 
+0

J'ai testé le code et chacune des méthodes a réussi les tests. – DataEngineer

Répondre

2

genre Hash # a le même effet (au moins pour mon test de base) comme Hash # to_a suivi par tries Array #.

hash = {b: 2, a: 1} 
hash.to_a.sort # => [[:a, 1, [:b, 2]] 
hash.sort  # => the same 

Maintenant, regardons #each, à la fois sur Hash et Array.

Lorsque vous fournissez deux arguments au bloc, cela peut gérer les deux cas. Pour le hachage, le premier argument sera la clé et le second sera la valeur. Pour le tableau imbriqué, les valeurs se essentiellement splatted vers les args:

[[:a, 1, 2], [:b, 3, 4]].each { |x, y, z| puts "#{x}-#{y}-#{z}" } 
# => a-1-2 
# => b-3-4 

Donc, fondamentalement, vous devriez penser à trier Hash # pour être un raccourci vers Dièse # to_a suivi de tableau # sorte, et reconnaître que # chacun fonctionnera de la même manière sur un hachage qu'un hachage converti en tableau (un tableau imbriqué). Dans ce cas, peu importe l'approche que vous prenez. Clairement, si vous avez besoin de trier les itérations par les touches, vous devez utiliser tri.