2

这是我的 Rails 课程

class SkinnyEmployee
  include ActiveModel::Validations

  attr_accessor :uid, :name

  validates :uid, :presence => true

  def initialize(id, name)
    @uid = id
    @name = name
  end

  def ==(other)
    puts "Calling =="
    raise ArgumentError.new("other is nil or bad in "+self.to_s) if other.nil? or !other.instance_of?(SkinnyEmployee)
    return (self.class == other.class && self.uid == other.uid)
  end

  alias :eql? :==

end

我有一个 SkinnyEmployee 对象的哈希值。例如,

skinny_hash = {SkinnyEmployee.new("123", "xyz") => 1, SkinnyEmployee.new("456", "abc") => 2}

我有另一个要查找的 SkinnyEmployee 对象。例如,

entry = SkinnyEmployee.new("456", "abc")

当我做

skinny_hash.keys.index(entry)

正如预期的那样,我得到 1。但是当我这样做时

skinny_hash.has_key?(entry)

我弄错了。

这是为什么?没有has_key吗?也使用 == 或 eql? 查找哈希中是否存在密钥?

非常感谢您的帮助!

4

3 回答 3

0

首先,这让我发疯了。你所做的对我来说看起来绝对正确,而且,正如你已经知道的那样,它不起作用。

我可以带您部分解决问题:

http://ruby-doc.org/core-2.0.0/Object.html#method-i-hash

引用:

为此对象生成一个 Fixnum 哈希值。该函数必须具有 a.eql?(b) 蕴含 a.hash == b.hash 的性质。

哈希值与 eql 一起使用?通过 Hash 类来确定两个对象是否引用相同的哈希键。任何超过 Fixnum 容量的哈希值在使用前都会被截断。

我补充说:

def hash
    1
end

到你的 SkinnyEmployee 类和 has_key?开始返回真。显然这不是一个解决方案,但我认为它至少能让你走上通往解决方案的道路。

于 2013-10-17T00:19:45.910 回答
0

您已经覆盖了eql?使用的方法,Array#index但没有覆盖 使用的hash方法Hash#has_key?

来自Ruby文档Object#hash

Generates a Fixnum hash value for this object. This function must have the property that a.eql?(b) implies a.hash == b.hash.

当且仅当对象在内存中占用相同空间时,Object#hashand方法才返回相等。Object#eql?如果比较的数组具有相同的元素,则某些类Array会覆盖这两种方法以返回 true。

对于您的情况,您可以定义如下hash方法:

  def hash
      "#{self.class}_#{self.uid}".hash
  end

这将满足上面给出的方法的文档标准hash

于 2013-10-17T00:30:45.380 回答
0

发生这种情况是因为您用作键的对象与您用于搜索键的对象不同。

每次调用 SkinnyEmployee.new 时,它都会创建一个新的、不同的对象。例如

employee_1 = SkinnyEmployee.new("123", "xyz")
employee_2 = SkinnyEmployee.new("123", "xyz")

employee_1 == employee_1 #=> true
employee_2 == employee_2 #=> true
employee_2 == employee_1 #=> false

如果您同时调用object_id两者employee_1employee_2您会注意到它为您提供了不同的 id。

使用has_key?将检查完全相同的对象,如果您使用SkinnyEmployee.new("456", "abc").

您需要一种方法来检索完全相同的对象,将其存储在变量或数据库中,您将其用作键并将其用作 has_key 的属性?让它工作。

希望这可以帮到你。

于 2013-10-17T00:45:43.943 回答