Difference Between map and each
each
simply iterates over the given enumerable, running the block for each value. It discards the return value of the block, and each simply returns the original object it was called on:
[1, 2, 3].each do |x|
x + 1
end # => [1, 2, 3]
This is simply a nicer, more universal way of doing a traditional iterating for
loop, and each
is much preferred over for
loops in Ruby (in fact, I don't think I've ever used a for
loop in Ruby).
map
, however, iterates over each element, using the return value of the block to populate a new array at each respective index and return that new array:
[1, 2, 3].map do |x|
x + 1
end # => [2, 3, 4]
So it “maps” each element to a new one using the block given, hence the name “map”. Note that neither each
nor map
themselves modify the original collection. This is a concise, functional alternative to creating an array and pushing to it in an iterative loop.
JavaScript: Difference between .forEach() and .map()
They are not one and the same. Let me explain the difference.
forEach
: This iterates over a list and applies some operation with side effects to each list member (example: saving every list item to the database) and does not return anything.
map
: This iterates over a list, transforms each member of that list, and returns another list of the same size with the transformed members (example: transforming list of strings to uppercase). It does not mutate the array on which it is called (although the callback function may do so).
References
Array.prototype.forEach() - JavaScript | MDN
Array.prototype.map() - JavaScript | MDN
Array#each vs. Array#map
Array#each
executes the given block for each element of the array, then returns the array itself.
Array#map
also executes the given block for each element of the array, but returns a new array whose values are the return values of each iteration of the block.
Example: assume you have an array defined thusly:
arr = ["tokyo", "london", "rio"]
Then try executing each
:
arr.each { |element| element.capitalize }
# => ["tokyo", "london", "rio"]
Note the return value is simply the same array. The code inside the each
block gets executed, but the calculated values are not returned; and as the code has no side effects, this example performs no useful work.
In contrast, calling the array's map
method returns a new array whose elements are the return values of each round of executing the map
block:
arr.map { |element| element.capitalize }
# => ["Tokyo", "London", "Rio"]
jQuery map vs. each
The each
method is meant to be an immutable iterator, where as the map
method can be used as an iterator, but is really meant to manipulate the supplied array and return a new array.
Another important thing to note is that the each
function returns the original array while the map
function returns a new array. If you overuse the return value of the map function you can potentially waste a lot of memory.
For example:
var items = [1,2,3,4];
$.each(items, function() {
alert('this is ' + this);
});
var newItems = $.map(items, function(i) {
return i + 1;
});
// newItems is [2,3,4,5]
You can also use the map function to remove an item from an array. For example:
var items = [0,1,2,3,4,5,6,7,8,9];
var itemsLessThanEqualFive = $.map(items, function(i) {
// removes all items > 5
if (i > 5)
return null;
return i;
});
// itemsLessThanEqualFive = [0,1,2,3,4,5]
You'll also note that the this
is not mapped in the map
function. You will have to supply the first parameter in the callback (eg we used i
above). Ironically, the callback arguments used in the each method are the reverse of the callback arguments in the map function so be careful.
map(arr, function(elem, index) {});
// versus
each(arr, function(index, elem) {});
What is the difference between map, each, and collect?
each
is different from map
and collect
, but map
and collect
are the same (technically map
is an alias for collect
, but in my experience map
is used a lot more frequently).
each
performs the enclosed block for each element in the (Enumerable
) receiver:
[1,2,3,4].each {|n| puts n*2}
# Outputs:
# 2
# 4
# 6
# 8
map
and collect
produce a new Array
containing the results of the block applied to each element of the receiver:
[1,2,3,4].map {|n| n*2}
# => [2,4,6,8]
There's also map!
/ collect!
defined on Array
s; they modify the receiver in place:
a = [1,2,3,4]
a.map {|n| n*2} # => [2,4,6,8]
puts a.inspect # prints: "[1,2,3,4]"
a.map! {|n| n+1}
puts a.inspect # prints: "[2,3,4,5]"
What is really the difference between underscore _.each and _.map?
map
is intended to be a functional mapping method: its function argument should return a value, but is not expected to have any side-effects.
each
is just a functional replacement for an imperative for
loop: its purpose is to have an effect, and it is not expected to return any value.
For example, this would be a more appropriate use for map
:
var docs = getDocs();
var docTitles = _.map(docs, function (doc){
return doc.title;
});
// expect `docs` to be unchanged
Whereas this would be an appropriate use for each
:
var docs = getDocs();
_.each(docs, function (doc){
delete doc.niche;
});
// expect `docs` to be altered.
D: What difference between map and each?
each
performs an eager evaluation, while map
performs a lazy one.
This means that when you apply each
, every element is calculated immediately, while map
calculates its results only when you access them.
This also means that each
is unsuitable for infinite streams.
What is the big difference between forEach and map?
The difference is that forEach
"iterates over an array" and map
"iterates over an array and returns the result"
var numbers = [1, 4, 9];
var roots = numbers.forEach(Math.sqrt);
// roots is undefined, numbers is still [1, 4, 9]
var roots = numbers.map(Math.sqrt);
// roots is [1, 2, 3], numbers is still [1, 4, 9]
What's so good about map
? It keeps your code small and smart because you don't need to define anonymous functions for built-in functions.
var numbers = [1, 4, 9];
var roots = [];
numbers.forEach(function(val){ roots.push( Math.sqrt(val) ); });
// roots is now [1, 2, 3], numbers is still [1, 4, 9]
The value of returning the result (no pun intended) is proven in your existing example...
var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
var reformattedArray = kvArray.map(function(obj){ // <---------------- map
var rObj = {};
rObj[obj.key] = obj.value;
return rObj;
});
// reformattedArray is now [{1:10}, {2:20}, {3:30}],
// kvArray is still [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}]
var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
var reformattedArray = kvArray.forEach(function(obj){ // <---------------- forEach
var rObj = {};
rObj[obj.key] = obj.value;
return rObj;
});
// reformattedArray is now undefined,
// kvArray is still [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}]
Difference in output with map and each
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"]
Related Topics
Ruby Method Calls Declared in Class Body
Extract Links (Urls), with Nokogiri in Ruby, from a Href HTML Tags
Mongodb with Mongoid in Rails - Geospatial Indexing
Ruby Working on Array Elements in Groups of Four
Find Out If an Ip Is Within a Range of Ips
Ruby: How to Concatenate Array of Arrays into One
Install Latest Stable Version of Ruby Using Rbenv
Why Do I Need to Work Harder to Make My Rails Application Fit into a Restful Architecture
What Should Be Removed from Public Source Control in Ruby on Rails
Why 'Self' Method of Module Cannot Become a Singleton Method of Class
Finding What Is Common to Two Arrays
How to Get the Number of Days in a Given Month in Ruby, Accounting for Year
If Java People Go to Scala, C# Go to F#, Where Do Ruby People Go for Functional Nirvana
Generating Unique, Hard-To-Guess "Coupon" Codes
How to Remove Carriage Returns with Ruby
When Do We Use the "||=" Operator in Rails? What Is Its Significance