7

我有一个 ActiveRecord 对象的二元素数组,slots_to_import. 这些对象有begin_at列,因此也有属性。我试图获取具有唯一begin_at值的对象。唉,slots_to_import.uniq_by(&:begin_at)没有工作。但是这begin_at两个对象的值是相等的:

(rdb:1) p slots_to_import.first.begin_at == slots_to_import.last.begin_at
true
(rdb:1) p slots_to_import.uniq_by(&:begin_at).map(&:begin_at)
[Mon, 26 Nov 2012 19:00:00 UTC +00:00, Mon, 26 Nov 2012 19:00:00 UTC +00:00]
(rdb:1) p [slots_to_import.first.begin_at, slots_to_import.last.begin_at].uniq
[Mon, 26 Nov 2012 19:00:00 UTC +00:00, Mon, 26 Nov 2012 19:00:00 UTC +00:00]

更多检查:

(rdb:1) p [slots_to_import.first.begin_at.to_datetime, slots_to_import.last.begin_at.to_datetime].uniq
[Mon, 26 Nov 2012 19:00:00 +0000]
(rdb:1) p [slots_to_import.first.begin_at.usec, slots_to_import.last.begin_at.usec].uniq
[0]
(rdb:1) p [slots_to_import.first.begin_at.to_f, slots_to_import.last.begin_at.to_f].uniq
[1353956400.0]
(rdb:1) p [slots_to_import.first.begin_at.utc, slots_to_import.last.begin_at.utc].uniq
[Mon, 26 Nov 2012 19:00:00 +0000]
(rdb:1) p [slots_to_import.first.begin_at, slots_to_import.last.begin_at].uniq
[Mon, 26 Nov 2012 19:00:00 UTC +00:00, Mon, 26 Nov 2012 19:00:00 UTC +00:00]

我想也许 uniq 正在检查它们是否是同一个对象(因为它们不是)。但是不,我的 rails 控制台中的一些闲逛表明它不使用对象 id 检查:

1.8.7 :111 > x = Time.zone.parse("Mon, 29 Oct 2012 19:29:17 UTC +00:00")
 => Mon, 29 Oct 2012 19:29:17 UTC +00:00 
1.8.7 :112 > y = Time.zone.parse("Mon, 29 Oct 2012 19:29:17 UTC +00:00")
 => Mon, 29 Oct 2012 19:29:17 UTC +00:00 
1.8.7 :113 > x == y
 => true 
1.8.7 :114 > [x, y].uniq
 => [Mon, 29 Oct 2012 19:29:17 UTC +00:00] 

我正在使用 Ruby 1.8.7p358 和 ActiveSupport 3.2.0。顺便说一句,我可以通过简单地添加来解决我自己的问题 a to_datetime,但我真的很好奇为什么这在没有转换的情况下不起作用。

4

3 回答 3

1

我以为您使用的是普通Time对象,所以我time.c从 Ruby 平台源代码 (1.9.3) 开始。如果它们是 Ruby 1.9.3Time对象,您可以尝试:

[x.to_r, y.to_r]

现在我知道您正在处理ActiveSupport::TimeWithZone对象。(作为建议,下次您发布问题时最好提及此类关键信息。)以下是正文ActiveSupport::TimeWithZone#eql?

def eql?(other)
  utc == other
end

这是哈希函数:

alias :hash, :to_i

所以下一步是让你展示你从中得到了什么[x.utc, y.utc, x.to_i, y.to_i, x.utc.class, y.utc.class]

于 2012-10-30T04:23:27.720 回答
0

不同的微秒是我的猜测。2 个对象可以显示相同的检查字符串但不相等。

于 2012-10-30T01:05:51.323 回答
0
irb(main):017:0> x = 'a'
=> "a"
irb(main):018:0> y = 'a'
=> "a"
irb(main):019:0> x == y
=> true
irb(main):020:0> [x,y].uniq
=> ["a"]
irb(main):021:0> x.object_id == y.object_id
=> false
irb(main):024:0> x.hash == y.hash
=> true

Ruby 相等性测试基于值,而不是参考。如果你想比较它们是否引用同一个对象,你应该比较o.object_id

于 2012-10-30T03:45:40.540 回答