2017-07-06 1 views
1

Avec Ruby (2.4), je veux étendre la fonctionnalité de hachage de base pour rechercher des clés basées sur un tableau et retourner la valeur du premier élément qui peut être trouvé à partir de ce tableau. J'ai dans mon fichier lib/core_ext/hash_with_indifferent_access.rb ...Comment puis-je rechercher une valeur dans un hachage basé sur un tableau de clés?

class CaseInsensitiveHash < HashWithIndifferentAccess 
    # This method shouldn't need an override, but my tests say otherwise. 
    def [](key) 
    if key.kind_of?(Array) 
     find_by_arr(arr) 
    else 
     super convert_key(key) 
    end 
    end 

    protected 

    def convert_key(key) 
    key.respond_to?(:downcase) ? key.downcase : key 
    end 

    def find_by_arr(arr) 
    arr.inject(self){|h, k| h.to_h[k]} 
    end 

end 

Cependant, il ne fonctionne pas comme prévu. Dans mon code ci-dessous, la recherche 'h [["a", "b"]]' devrait produire "1", parce que le premier élément, "a", est une clé dans mon hachage.

2.4.0 :001 > h = {"a" => 1, "b" => 2} 
=> {"a"=>1, "b"=>2} 
2.4.0 :002 > h["a"] 
=> 1 
2.4.0 :003 > h[["a", "b"]] 
=> nil 

Comment puis-je modifier mon code pour que je puisse passer dans un tableau comme une clé à un hachage et il commence à rechercher des valeurs itérativement par chaque élément du tableau?

Répondre

1

Vous l'avez presque compris, mais le problème est que h = { ... } crée un Hash simple, pas celui auquel vous avez ajouté ces méthodes.

La première solution est de le faire:

h = CaseInsensitiveHash["a" => 1, "b" => 2] 

Ensuite, vous obtenez le bon type d'objet et votre méthode fonctionne actuellement.

Il y a une faute de frappe dans votre méthode [] qui peut être corrigé:

def [](key) 
    case key 
    when Array 
    find_by_arr(key) 
    else 
    super convert_key(key) 
    end 
end 

Votre référence à arr ne fonctionne pas parce que ce n'est pas défini.

La méthode find_by_arr renvoie également la dernière correspondance, pas la première. Cela peut être corrigé:

def find_by_arr(arr) 
    self[arr.first { |key| self[key] }] 
end