集合上的地图返回nil

时间:2016-11-05 08:49:14

标签: ruby

我目前正在学习红宝石并玩弄收藏品。我现在陷入了一个问题,需要一些帮助来理解为什么有些东西会这样运作。

所以,我们有一个简单的数组:

arr = ["cat", "dog", "pig", "goat"]

现在,我想让每一个元素上升并反转。我认为的第一件事就是三元:

modified = arr.each_with_index.map do |el, idx| 
    ((idx + 1) % 2 == 0) ? el.upcase.reverse : el
end

没什么大不了的。但我玩了一遍,想出了另一个解决方案。

modified = arr.each_with_index.map do |el, idx| 
    el.upcase.reverse if (idx + 1) % 2 == 0
    el unless (idx + 1) % 2 == 0
end

这对我来说似乎是正确的,但不是对翻译来说。

通过三元组我得到了结果:

["cat", "GOD", "pig", "TAOG"]

但是采用后一种方法:

["cat", nil, "pig", nil]

有人可以解释为什么后者不起作用(它会在每一秒钟上放置一次)吗?

如果我使用常规的if-else,它会再次起作用。

modified = arr.each_with_index.map do |el, idx| 
    if (idx + 1) % 2 == 0
        el.upcase.reverse
    else
        el
    end
end

常规if如何与one-liners不同?

提前致谢!

2 个答案:

答案 0 :(得分:2)

Array#map将使用参数中传递的块的返回值来构建新数组。

由于您没有使用任何return语句,因此它始终是最后评估的表达式。

在您的第一个和第三个解决方案中,您始终“点击”elel.upcase.reverse

在您的第二个解决方案中,当(idx + 1) % 2 == 0时,您没有做任何事情,因此您只需返回nil

希望这有帮助。

注意:查看Integer#odd?Integer#even?

答案 1 :(得分:1)

下面

modified = arr.each_with_index.map do |el, idx| 
    el.upcase.reverse if (idx + 1) % 2 == 0
    el unless (idx + 1) % 2 == 0
end

如果条件满足,则此行el unless (idx + 1) % 2 == 0 #=> nil。数组["cat", nil, "pig", nil]如下。

另一种方法

arr.map.with_index { |str,i|  i.odd? ? str.upcase.reverse : str }
#=> ["cat", "GOD", "pig", "TAOG"]