Need a simple explanation of the inject method

前端 未结 16 1405
天涯浪人
天涯浪人 2020-11-28 17:49
[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10

I\'m looking at this code but my brain is not registering how the number 1

相关标签:
16条回答
  • 2020-11-28 18:24

    [1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10

    In plain English, you are going through (iterating) through this array ([1,2,3,4]). You will iterate through this array 4 times, because there are 4 elements (1, 2, 3, and 4). The inject method has 1 argument (the number 0), and you will add that argument to the 1st element (0 + 1. This equals 1). 1 is saved in the "result". Then you add that result (which is 1) to the next element (1 + 2. This is 3). This will now be saved as the result. Keep going: 3 + 3 equals 6. And finally, 6 + 4 equals 10.

    0 讨论(0)
  • 2020-11-28 18:27

    Is the same as this:

    [1,2,3,4].inject(:+)
    => 10
    
    0 讨论(0)
  • 2020-11-28 18:29

    inject takes a value to start with (the 0 in your example), and a block, and it runs that block once for each element of the list.

    1. On the first iteration, it passes in the value you provided as the starting value, and the first element of the list, and it saves the value that your block returned (in this case result + element).
    2. It then runs the block again, passing in the result from the first iteration as the first argument, and the second element from the list as the second argument, again saving the result.
    3. It continues this way until it has consumed all elements of the list.

    The easiest way to explain this may be to show how each step works, for your example; this is an imaginary set of steps showing how this result could be evaluated:

    [1, 2, 3, 4].inject(0) { |result, element| result + element }
    [2, 3, 4].inject(0 + 1) { |result, element| result + element }
    [3, 4].inject((0 + 1) + 2) { |result, element| result + element }
    [4].inject(((0 + 1) + 2) + 3) { |result, element| result + element }
    [].inject((((0 + 1) + 2) + 3) + 4) { |result, element| result + element }
    (((0 + 1) + 2) + 3) + 4
    10
    
    0 讨论(0)
  • 2020-11-28 18:29

    tldr; inject differs from map in one important way: inject returns the value of the last execution of the block whereas map returns the array it iterated over.

    More than that the value of each block execution passed into the next execution via the first parameter (result in this case) and you can initialize that value (the (0) part).

    Your above example could be written using map like this:

    result = 0 # initialize result
    [1, 2, 3, 4].map { |element| result += element }
    # result => 10
    

    Same effect but inject is more concise here.

    You'll often find an assignment happens in the map block, whereas an evaluation happens in the inject block.

    Which method you choose depends on the scope you want for result. When to not use it would be something like this:

    result = [1, 2, 3, 4].inject(0) { |x, element| x + element }
    

    You might be like all, "Lookie me, I just combined that all into one line," but you also temporarily allocated memory for x as a scratch variable that wasn't necessary since you already had result to work with.

    0 讨论(0)
  • 2020-11-28 18:29

    It's just reduce or fold, if you're familiar with other languages.

    0 讨论(0)
  • 2020-11-28 18:34

    There is another form of .inject() method That is very helpful [4,5].inject(&:+) That will add up all the element of the area

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