2017-07-06 5 views
1

Mit Ruby (2.4) möchte ich die Kern-Hash-Funktionalität erweitern, um auf der Basis eines Arrays nach Schlüsseln zu suchen und den Wert des ersten Elements zurückzugeben, das von diesem Array gefunden werden kann. Ich habe dies in meinem lib/core_ext/hash_with_indifferent_access.rb Datei ...Wie suche ich einen Wert in einem Hash basierend auf einem Array von Schlüsseln?

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 

Es wird jedoch nicht wie erwartet funktioniert. In meinem Code unten sollte die Suche 'h [["a", "b"]]' "1" erzeugen, weil das erste Element, "a", ein Schlüssel in meinem Hash ist.

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 

Wie kann ich meinen Code ändern, so dass ich in einem Array als Schlüssel zu einem Hash passieren kann und es beginnt iterativ für Werte der Suche von jedem Element in dem Array?

Antwort

1

Sie haben es fast schon, aber das Problem ist, dass h = { ... } einen plain-alten Hash erstellt, nicht die Art, die Sie diese Methoden hinzugefügt haben.

Die erste Lösung ist, dies zu tun:

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

Dann erhalten Sie die richtige Art von Objekt und Ihre Methode tatsächlich läuft.

Es ist ein Tippfehler in Ihrer [] Methode, die korrigiert werden kann:

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

Ihr Bezug auf arr funktioniert nicht, weil das nicht definiert ist.

Die Methode find_by_arr gibt auch die letzte Übereinstimmung zurück, nicht die erste. Dies kann behoben werden:

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