我需要帮助找出地图与以下代码中每个地图之间存在差异的原因。
j = "This is an awesome string"
j.split('').map do |char|
char.next! if char =~ /[A-Za-z]/
end
返回:
["U", "i", "j", "t", nil, "j", "t", nil, "b", "o", nil, "b", "x", "f", "t", "p", "n", "f", nil, "t", "u", "s", "j", "o", "h"]
但
j.split('').each do |char|
char.next! if char =~ /[A-Za-z]/
返回:
["U", "i", "j", "t", " ", "j", "t", " ", "b", "o", " ", "b", "x", "f", "t", "p", "n", "f", " ", "t", "u", "s", "j", "o", "h"]
为什么从map
到each
的更改会删除nil?
答案 0 :(得分:5)
因为Array#each
会返回接收器本身。但Array#map
, maps ,每个当前字符,您传递给块,并带有当前计算结果。
使用#map
,条件if char =~ /[A-Za-z]/
评估为 falsy ,对于每个传递的元素,例如" "
。因此阻止映射nil
,同时发现" "
或if
条件评估为 falsy 的任何元素。但#each
在每次迭代完成后忘记了阻止结果,但#map
没有。
如果您查看输出,则可以看到所有nil
(s)位于" "
的相同位置。这一观察也决定了我刚才提到的行为。
在Ruby中,每个代码块(如类的定义,方法定义,块定义)都返回其最后一个语句。在#map
区块中,if modifier
之后没有语句,因此重新运行nil
。
在Ruby> = 2.1.1中,我看到方法将其名称作为符号返回。但是当你调用它时,它将返回它的最后一个语句。如果方法体为空,则为nil
。
看下面: -
[1] pry(main)> def foo
[1] pry(main)* end
=> :foo
[2] pry(main)> foo
=> nil
[3] pry(main)> def baz
[3] pry(main)* 12
[3] pry(main)* end
=> :baz
[4] pry(main)> baz
=> 12
<强>更新强>
从@asquirrel的评论中,我有了一个主意。您可以用Ruby方式编写代码: -
"This is an awesome string".gsub(/[a-z]/i).map(&:next)
# => ["U", "i", "j", "t", "j", "t", "b", "o", "b",
# "x", "f", "t", "p", "n", "f", "t", "u", "s", "j", "o", "h"]
<强> UPDATE1 强>
j = "This is an awesome string"
array = j.split('').map do |char|
char =~ /[A-Za-z]/ ? char.next : char
end
p array
# >> ["U", "i", "j", "t", " ", "j", "t", " ", "b", "o", " ", "b",
# "x", "f", "t", "p", "n", "f", " ", "t", "u", "s", "j", "o", "h"]