How to understand Ruby's .each and .map

后端 未结 5 511
予麋鹿
予麋鹿 2021-01-18 21:00

I am having trouble understanding the differences between map and each, and where and when to use them.

I read \"What does map do?\" and \

相关标签:
5条回答
  • 2021-01-18 21:30

    The difference is that each is performing an action on each element in the array, returning the original array. The action performed possibly mutated the element.

    Whereas map is performing an action on each element in the array and returning its result as an array.

    0 讨论(0)
  • 2021-01-18 21:32

    The map method takes an enum given some block, and iterates through it doing some logic. In your case the logic is x+1. As you say it will not mutate anything unless you use !.

    each is simply returning the array that is being called.

    Let's take an example of:

    names = ["bob"]
    

    If we do:

    names.each{|names| names + "somestring"}
    

    the output is still ["bob"]. The reason your second example is different is due to the puts.

    As an exercise try doing:

    y = [1,2,3].each {|x| puts x + 1}
    

    You will get:

    2
    3
    4
     [1,2,3]
    
    0 讨论(0)
  • 2021-01-18 21:32

    tl;dr: I use map if I want to change my collection, apply a transformation on it, end up with something different. I use each if I just need to visit every element in a collection.

    Key point is: you should use map if you want to apply a transformation on an array (an enumerable in reality, but let's keep it simple at the beginning). Otherwise, if you don't need to change your array, you can simply use each.

    Note that in the code below you are not mutating the array but you are simply take advantage of the local string to print each string with a suffix.

    names = ['danil', 'edmund']
    names.each { |name| puts name + ' is a programmer' }
    

    Obviously, you could do the same with map but in this case you don't need it and you have to use an each too to print every element. The code would be

    names = ['danil', 'edmund']
    names.map! { |name| name + ' is a programmer' }
    # or names = names.map { |name| name + ' is a programmer' }
    name.each { |name| puts name }
    
    0 讨论(0)
  • 2021-01-18 21:36

    In the first case, map:

     z = [1,2,3].map {|x| x + 1}
    

    will take each element in the given array and perform the operation in the block and return a new array, so here it returns [2,3,4].

    .each executes the block for each of the elements in the array, and it will not change anything in the array, so here it performs x + 1, but it doesn't store it anywhere, hence in the second case it just returns the array.

    Now in the third example you posted, you are printing output in the block itself. Again, there is no change in the array itself.

    0 讨论(0)
  • 2021-01-18 21:41

    This is covered in Ruby's documentation in multiple places but the easiest to understand for your use is in the Array documentation for each:

    each { |item| block } → ary
    each → Enumerator
    

    Calls the given block once for each element in self, passing that element as a parameter. Returns the array itself.

    If no block is given, an Enumerator is returned.

    a = [ "a", "b", "c" ]
    a.each {|x| print x, " -- " }
    

    produces:

    a -- b -- c --
    

    Note that it says "Returns the array itself."

    Compare that to map:

    map { |item| block } → new_ary
    map → Enumerator
    

    Invokes the given block once for each element of self.

    Creates a new array containing the values returned by the block.

    See also Enumerable#collect.

    If no block is given, an Enumerator is returned instead.

    a = [ "a", "b", "c", "d" ]
    a.collect { |x| x + "!" }         #=> ["a!", "b!", "c!", "d!"]
    a.map.with_index { |x, i| x * i } #=> ["", "b", "cc", "ffffd"]
    a                                 #=> ["a", "b", "c", "d"]
    

    Note that it says "Creates a new array containing the values returned by the block."

    This example should help knowing the above:

    foo = [1,2,3]
    foo.each { |i| puts i + 1 } # => [1, 2, 3]
    foo.map { |i| i + 1 } # => [2, 3, 4]
    
    # >> 2
    # >> 3
    # >> 4
    

    where # => is the return value of the block and # >> is the captured STDOUT from puts.

    And, knowing all that, use each when you want to display elements in the array or extract and reuse those elements as parameters or to build things. Use map when you want to change the elements of the array into something else.

    0 讨论(0)
提交回复
热议问题