2010-09-07 14 views
5

ich eine rubin Hash habe wie diese
h = {"a" => "1", "b" => "", "c" => "2"}
Jetzt habe ich eine Ruby-Funktion, die diesen Hash auswertet und gibt true zurück, wenn sie einen Schlüssel mit einem leeren Wert finden. Ich habe die folgende Funktion, die immer true zurück, auch wenn alle Schlüssel in der Hash nicht leerSuche Rubin Hash für leeren Wert

def hash_has_blank(hsh) 
    hsh.each do |k,v| 
    if v.empty? 
     return true 
    end 
    end 
    return false 
end 

Was mache ich hier falsch? Bitte helfen

Danke, Abhi

+2

Dies funktioniert gut.Was ist ein Beispiel für einen Hash, in dem Sie dieses Problem sehen (da Ihr 'h' einen leeren Wert hat) – DanSingerman

Antwort

8

Ich hoffe‘ bereit, hier etwas Rubinkarikatur zu lernen. Ich würde eine solche Funktion nicht global definieren wie Sie. Wenn es auf einem Hash eine Operation ist, als sollte es eine Instanz-Methode für die Hash-Klasse sein, das Sie es wie folgt tun:

class Hash 
    def has_blank? 
    self.reject{|k,v| !v.nil? || v.length > 0}.size > 0 
    end 
end 

reject einen neuen Hash mit allen leeren Strings zurückgeben, und als es sein wird, überprüft, wie groß dieser neue Hash ist.

eine möglicherweise effizientere Art und Weise (es sollte das gesamte Array nicht durchqueren):

class Hash 
    def has_blank? 
    self.values.any?{|v| v.nil? || v.length == 0} 
    end 
end 

Aber das wird noch die ganze Hash durchqueren, wenn kein leerer Wert ist

ich habe mich verändert Die empty? zu !nil? || length >0 weil ich nicht weiß, wie Ihre empty Methode funktioniert.

+1

Nicht sehr effizient, da Sie 1) den gesamten Hash durchlaufen und 2) eine weitere Struktur unnötig machen. –

+0

Sie haben Recht, wenn Sie meine Antwort aktualisieren. 'include?' sollte nicht den ganzen Hash durchlaufen, wenn es ein Vorkommen von nil findet. Aber wenn Sie fast immer Hashs haben, die keine leeren Werte haben, sollte es überhaupt keine Rolle spielen, denn um "falsch" zurückzugeben, MUSS die Funktion IMMER den gesamten Hash durchlaufen. – jigfox

+0

Natürlich sollte jede Lösung den gesamten Hash durchlaufen, wenn keine Leerzeichen vorhanden sind. –

17

Try this:

def hash_has_blank hsh 
    hsh.values.any? &:empty? 
end 

Oder:

def hash_has_blank hsh 
    hsh.values.any?{|i|i.empty?} 
end 

Wenn Sie eine alte 1.8.x Rubin verwenden

+4

Sie könnten 'hsh.each_value.any? &: leer? 'in ruby> = 1.8.7 um zu vermeiden, dass es in ein Array umgewandelt wird. Aber das könnte nur für große Hashes von Bedeutung sein. –

+0

Ich stimme Ihnen zu, mit Enumerator ist besser. – Nakilon

+0

Warnung: Dies wird bei Hash-Werten ausgelöst, die auf die 'leere?' Methode reagieren. Z.B. 'hash_has_blank ({a: []}) == true', was möglicherweise nicht das erwartete Verhalten ist. Der Vorschlag von @ steenslag kann oft angemessener sein. – Automatico

4

Wenn Sie wollen einfach nur überprüfen, ob einer der Werte ein leerer String könnte man

h.has_value?('') 

tun, aber Ihre Funktion scheint gut zu funktionieren.

4

Ich würde eine Refactoring Ihrer Modelldomäne erwägen. Offensichtlich repräsentiert das Hash etwas Greifbares. Warum nicht ein Objekt machen? Wenn das Element vollständig durch einen Hash dargestellt werden kann, möchten Sie vielleicht Hash ableiten. Wenn es komplizierter ist, kann der Hash ein Attribut sein.

Zweitens kann der Grund, für den Sie Leerzeichen überprüfen, benannt werden, um Ihre Domäne besser widerzuspiegeln. Sie haben uns nicht das "Warum" gesagt, aber nehmen wir an, dass Ihr Artikel nur gültig ist, wenn er keine leeren Werte enthält.

class MyItem < Hash 

    def valid? 
    !invalid? 
    end 

    def invalid? 
    values.any?{|i| i.empty?} 
    end 
end 

Der Punkt ist, wenn Sie ein Vokabular, das Sinn herstellen können in Ihrer Domain macht, wird Ihr Code sauberer und verständlich sein. Die Verwendung eines Hash ist nur ein Mittel zum Zweck, und Sie verwenden besser beschreibende, domänenspezifische Begriffe.

Mit dem obigen Beispiel würden Sie in der Lage zu tun: für mich

my_item = MyItem["a" => "1", "b" => "", "c" => "2"] 

my_item.valid? #=> false 
+0

Dies ist ein sauberer Weg, es zu tun. Jigfox Lösung macht es für mich – eabhvee

+0

Wenn das ein Wegwerf-Skript war, dann gut. Aber in einem Code-Review würde ich einen Affen-Patch einer grundlegenden Datenstruktur zugunsten einer korrekten Objektmodellierung ablehnen. –

Verwandte Themen