2012-10-29 23 views
7

İki elemanlı ActiveRecord nesnesi var, slots_to_import. Bu nesneler begin_at sütunlara ve dolayısıyla özelliklere sahiptir. Benzersiz begin_at değerlerine sahip nesneler almaya çalışıyordum. Ne yazık ki, slots_to_import.uniq_by(&:begin_at) çalışmadı. Ama begin_at değerleri iki nesne için eşittir:Ruby tuhaflığı: x == y && [x, y] .uniq == [x, y]

(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] 

Biraz daha etrafında kontrol:

(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] 

I (onlar değildi beri) belki de uniq aynı nesne olup olmadığı kontrol ediyordu düşündüm.

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 ve ActiveSupport 3.2.0 kullanıyorum: Ama hayır, benim raylar konsolda bazı noodling bir nesne kimliği denetimi kullanmayan bana gösterdi. BTW, kendi sorunumu sadece to_datetime ekleyerek çözebilirim, ancak bunun neden dönüşüm olmadan çalışmadığını merak ediyorum.

+4

'x.hash' ve' y.hash' sonuçlarını karşılaştırmayı denediniz mi? – hammar

+0

@hammar: "uniq_by" Hash tabanlı olarak görülmesi ilginç bir fikir. –

+0

@hammar 'x.hash' ve' y.hash' da eşittir! - '(rdb: 1) p slots_to_import.first.begin_at.hash == slots_to_import.last.begin_at.hash => true ' – ehsanul

cevap

0

Farklı mikrosaniyeler benim tahminimdir. 2 nesne aynı inceleme dizesini gösterebilir, ancak eşit olmaz.

+0

İnceleme dizesi hakkında haklısınız, ancak mikrosaniyeler hakkında yanlışsınız. Sorumlulukta "usec" yöntemini kontrol ettiğimi not edersiniz. Alıntı: '(rdb: 1) p [slots_to_import.first.begin_at.usec, slots_to_import.last.begin_at.usec] .uniq => [0]' – ehsanul

+0

Ayrıca, farklı mikrosaniye ile iki kez/kez düşünmüyorum Birbirine == olacak: '1.8.7: 006> Time.now == Time.now => false' – ehsanul

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 

Yakut eşitlik testi, referans değil, değere dayanır. Eğer aynı nesneye başvuran eğer karşılaştırmak istiyorsanız, ben düz Time nesnelerle çalışacağını sanıyordum o.object_id

+0

Değeri önemsemiyorum, referans değil. Snippet'inizde değerler eşittir ve "uniq" bunu yansıtır. Benimkinde değerler eşittir, ancak uniq bunu yansıtmaz. – ehsanul

1

karşılaştırmak gerekir, bu yüzden Ruby platformu kaynağından (1.9.3) den time.c bakarak başladık. onlar Ruby 1.9.3 Time nesneler olsaydı, deneyebilirsiniz:

[x.to_r, y.to_r] 

Şimdi biliyorum sen ActiveSupport::TimeWithZone nesnelerle çalışıyoruz. (Bir öneri olarak, size bir soru gönderebilir bu sefere gibi önemli bilgileri söz iyi olurdu.) İşte ActiveSupport::TimeWithZone#eql? gövdesidir:

def eql?(other) 
    utc == other 
end 

Ve burada hash fonksiyonu geçerli:

alias :hash, :to_i 

Bir sonraki adım, [x.utc, y.utc, x.to_i, y.to_i, x.utc.class, y.utc.class]'dan ne aldığınızı göstermeniz içindir.

+0

Bu ruby ​​1.8.7p358 için mi?"NoMethodError: undefined method", "Time.now.to_r" komutunu kullanıyorum. Ayrıca, bu özel 'ActiveSupport :: TimeWithZone' nesneleri' to_r' yöntemini de eksik olan 'DateTime' nesneleriyle desteklenir. – ehsanul

+0

Ruby 1.9.3 kaynağına bakıyordum. Zamanım varsa, Ruby 1.8 kaynağına bakabilirim ... bu arada "to_f" yi deneyin. –

+0

Teşekkürler! Zaten bir “to_f” kontrolünü yaptım ve orijinal soruda da bu konuya eşit olduklarını ekledim. – ehsanul

İlgili konular