\"1\", \"b\" => \"\", \"c\" => \"2\"} Now I have a ruby function which evaluates this hash and returns true if it finds a key with an 开发者_开发问答empty" />
开发者

Search ruby hash for empty value

I have a ruby hash like this

h = {"a" => "1", "b" => "", "c" => "2"}

Now I have a ruby function which evaluates this hash and returns true if it finds a key with an 开发者_开发问答empty value. I have the following function which always returns true even if all keys in the hash are not empty

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

What am I doing wrong here?


Try this:

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

Or:

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

If you are using an old 1.8.x Ruby


I hope you're ready to learn some ruby magic here. I wouldn't define such a function globally like you did. If it's an operation on a hash, than it should be an instance method on the Hash class you can do it like this:

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

reject will return a new hash with all the empty strings, and than it will be checked how big this new hash is.

a possibly more efficient way (it shouldn't traverse the whole array):

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

But this will still traverse the whole hash, if there is no empty value

I've changed the empty? to !nil? || length >0 because I don't know how your empty method works.


If you just want to check if any of the values is an empty string you could do

h.has_value?('')

but your function seems to work fine.


I'd consider refactoring your model domain. Obviously the hash represents something tangible. Why not make it an object? If the item can be completely represented by a hash, you may wish to subclass Hash. If it's more complicated, the hash can be an attribute.

Secondly, the reason for which you are checking blanks can be named to better reflect your domain. You haven't told us the "why", but let's assume that your Item is only valid if it doesn't have any blank values.

class MyItem < Hash

  def valid?
    !invalid?
  end

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

The point is, if you can establish a vocabulary that makes sense in your domain, your code will be cleaner and more understandable. Using a Hash is just a means to an end and you'd be better off using more descriptive, domain-specific terms.

Using the example above, you'd be able to do:

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

my_item.valid? #=> false
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜