2

由于我在 Rails 应用程序中处理了很多时间,因此我还想在某些地方将它们用作哈希键。但是,它似乎并没有像我预期的那样工作。

创建初始哈希工作正常。例如,以下将起作用:

>> hash = {1.week => 'abc', 1.month => 'def'}

但是,无法从哈希中检索值:

>> hash[1.month]
=> nil

一些进一步的调查向我展示了这样做的原因:

>> 1.week.eql? 1.week
=> false

这是非常出乎意料的

此外,这些对象的行为似乎与 FixNum 类的普通对象不同。对于普通的 FixNum 对象,object_id 的值似乎总是相同的,例如:

>> 15.object_id
=> 31
>> 15.object_id
=> 31

对于持续时间,这是不同的,尽管它们来自同一类

>> 1.month.class
=> Fixnum
>> 1.month.object_id
=> 70305513092140
>> 1.month.object_id
=> 70305513086860

因此,似乎对象总是不同的,这就是哈希不起作用的原因。唯一的解决方案是使用完全相同的对象进行访问:

>> a = 1.month
=> 1 month
>> hash = {a => 'b'}
=> {1 month=>"b"}
>> hash[a]
=> "b"

显然,如果您有很多具有动态创建持续时间的对象,这并不总是可行的。

按持续时间分组也不起作用:

>> limits.group_by(&:duration)
=> #<OrderedHash {1 month=>[#<Limit:0x7fe28e441380>], 1 month=>[#<Limit:0x7fe28e4290c8>]}>

所以,我想知道是否有可能以某种方式让持续时间作为哈希键工作?到目前为止,我还没有找到一个好的解决方案,我不确定是否有一个。重要的是,像 (Time.now - duration) 这样的函数应该继续工作。

仅供参考:我的 Ruby 版本 - 1.8.7,Rails 版本 - 2.3.18

4

1 回答 1

0

哇,这是一个奇怪的发现。这确实有效,我无法打破它,但它似乎有点脆弱:

hash = {1.year.inspect => "val1", 2.month.inspect => "val2", (1.year-4.days).inspect => "val3"}
 => {"1 year"=>"val1", "2 months"=>"val2", "1 year and -4 days"=>"val3"}

hash[2.months.inspect]
 => "val2" 

hash[(1.year-4.days).inspect]
 => "val3" 

并恢复持续时间

hash.keys.collect{|k| eval(k.gsub(" and ","+").split(" ").join("."))}
 => [1 year, 2 months, 1 year and -4 days] 
于 2013-08-26T09:04:49.623 回答