Array#reject和Array#map iterater的行为

时间:2015-11-24 13:50:09

标签: ruby

我有一个日期哈希:

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表现不同?

2 个答案:

答案 0 :(得分:1)

http://ruby-doc.org/core-2.2.3/Hash.html#method-i-reject

Hash#reject生成块的键和值。 i只是关键。你的钥匙是符号;可能是符号上的数组访问器(i[1])返回nil

我想,

Hash#map不是一件好事。您可能正在Enumerable#mapHashEnumerable,因此您仍然可以在哈希值上调用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)

rejectHash上的一个方法,它采用带有两个块变量的块:键和值。如果你传递一个只有一个变量的块,如下所示:

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)| ...}

xy将限制性地成为关键和价值。

可能您感到困惑,因为Array#reject仅使用一个变量进行阻止,并且与Hash#reject的工作方式不同。