Because Array#each
returns the receiver itself. But Array#map
, maps, each current character, you passed to the block, with the current computation result.
With #map
, the condition if char =~ /[A-Za-z]/
evalutated as falsy, for each passed element like " "
. Thus block mapped nil
while it founds " "
or any element for which if
condition evaluated as falsy. But #each
forgets about the block result after each iteration is completed, But #map
doesn't.
If you look at the output, you can see all nil
(s) are in the same position of " "
. This observation also dictates about the behaviour I just mentioned above.
In Ruby, every block of code, like definition of class, method definitions, block definitions returns its last statement. In your #map
block, there is no statements, after the if modifier
, so it reruns nil
.
In Ruby >= 2.1.1 I saw method to returns its names as a symbol. But when you will invoke it, then it will return its last statement. If the method body is empty, then nil
.
Look below :-
[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
update
From the comment of @asquirrel, I got an idea. You could write your code a more Ruby way :-
"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"]