我有一个日期哈希:
values = {a: Time.now, b: Time.now - 3.days}
# => {:a=>2015-11-24 22:35:56 +0900, :b=>2015-11-21 22:35:56 +0900}
要选择日期在一天之内的值,我写道:
values.reject{|i, v| v < Time.now - 1.day}
# => {:a=>2015-11-24 22:35:56 +0900}
当我使用i[1]
代替v
时,这不起作用,
values.reject{|i| i[1] < Time.now - 1.day}
# => NoMethodError: undefined method `<' for nil:NilClass
与map
同时有效。
values.map{|i| i[1]}
# => [2015-11-24 22:35:56 +0900, 2015-11-21 22:35:56 +0900]
为什么Array#reject
表现不同?
答案 0 :(得分:1)
http://ruby-doc.org/core-2.2.3/Hash.html#method-i-reject
Hash#reject
生成块的键和值。 i
只是关键。你的钥匙是符号;可能是符号上的数组访问器(i[1]
)返回nil
。
Hash#map
不是一件好事。您可能正在Enumerable#map
。 Hash
是Enumerable
,因此您仍然可以在哈希值上调用map
。
http://ruby-doc.org/core-2.2.3/Enumerable.html#method-i-map
Enumerable#map
将散列中的每个键值对作为2元素数组:[:a, 2015-11-24 22:35:56 +0900]
BTW在许多语言中都称为关联数组。 Rubyists通常称它们为哈希值。
答案 1 :(得分:1)
reject
是Hash
上的一个方法,它采用带有两个块变量的块:键和值。如果你传递一个只有一个变量的块,如下所示:
some_hash.reject{|x| ...}
然后将为x
分配密钥,并且无法访问其对应的值。执行x[1]
会调用[]
上的符号方法x
,这会产生nil
,因为:a
和:b
只有一个字符长。
另一方面,Enumerable#map
隐式地将哈希值转换为数组,并采用具有一个块变量的块。如果您实际传递了一个带有一个变量的块,如下所示:
some_hash.map{|x| ...}
然后x
将是一个具有键值对的数组。执行x[1]
调用数组方法[]
,并返回哈希值。
如果你改为传递一个包含两个变量的块:
some_hash.map{|x, y| ...}
然后将隐式应用销毁以调整变量的数量,即,live about将被解释为:
some_hash.map{|(x, y)| ...}
和x
,y
将限制性地成为关键和价值。
可能您感到困惑,因为Array#reject
仅使用一个变量进行阻止,并且与Hash#reject
的工作方式不同。