如何判断散列中是否有其他键而不是指定的键?

时间:2016-11-23 03:30:08

标签: ruby

说我有哈希:

a = {b: "asdfgh", c: "qwerty", d: "dvorak"}

我希望能够判断出除了我指定的键之外是否还有其他键,如下所示:

a.has_other_keys?(:b, :c, :d)
=> false
a.has_other_keys?(:c, :d)
=> true

但如果没有指定的键,我不希望它返回false:

a.has_other_keys?(:b, :c, :d, :e)
=> true

在ruby中有一种简单的方法吗?

4 个答案:

答案 0 :(得分:2)

Rails has an except/except! method返回删除了这些键的哈希值。如果您已经在使用Rails,则可以使用它

class Hash
  # Returns a hash that includes everything but the given keys.
  #   hash = { a: true, b: false, c: nil}
  #   hash.except(:c) # => { a: true, b: false}
  #   hash # => { a: true, b: false, c: nil}
  #
  # This is useful for limiting a set of parameters to everything but a few known toggles:
  #   @person.update(params[:person].except(:admin))
  def except(*keys)
    dup.except!(*keys)
  end

  # Replaces the hash without the given keys.
  #   hash = { a: true, b: false, c: nil}
  #   hash.except!(:c) # => { a: true, b: false}
  #   hash # => { a: true, b: false }
  def except!(*keys)
    keys.each { |key| delete(key) }
    self
  end
end

使用上面你可以:

bundle :002 >    a = {b: "asdfgh", c: "qwerty", d: "dvorak"}
 => {:b=>"asdfgh", :c=>"qwerty", :d=>"dvorak"}
bundle :006 >  a.except(:b)
 => {:c=>"qwerty", :d=>"dvorak"}
bundle :007 >  a.except(:b).length
 => 2
bundle :008 >  a.except(:b, :c, :d, :e).length
 => 0

在纯Ruby中,您可以执行以下操作:

2.2.2 :010 >  a.select{|x| ![:b, :c, :d, :e].include?(x)}
 => {}
2.2.2 :011 >  a.select{|x| ![:b, :c, :d, :e].include?(x)}.length
 => 0

答案 1 :(得分:2)

def subset_of_keys?(h, other_keys)
  (other_keys - h.keys).empty?
end

h  = { b: "asdfgh", c: "qwerty", d: "dvorak"}

subset_of_keys? h, [:d, :b]
  #=> true
subset_of_keys? h, [:b, :w, :d]
  #=> false

请参阅Array#-

答案 2 :(得分:2)

编辑:我刚才注意到Cary Swoveland的回答使用了同样的技术。他的答案首先在这里。

如果这不一定是高性能解决方案,您可以考虑使用Array算术(这是一个很好的Ruby功能)。

例如:

你的哈希:

a = {b: "asdfgh", c: "qwerty", d: "dvorak"}

我们已知的密钥:

known_keys = [:b, :c]

其余的键:

other_keys = a.keys - known_keys
other_keys.empty?

对于true / false语句,我们可以执行以下操作:

(a.keys - [:b, :c]).empty?

答案 3 :(得分:1)

您可以检查由键构造的集合是否相同:

require 'set'

class Hash
    def has_other_keys?(*keys)
        Set.new(keys) != Set.new(self.keys)
    end
end