[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10
나는이 코드를보고 있지만 뇌는 숫자 10이 어떻게 결과가 될 수 있는지 등록하지 않습니다. 여기서 무슨 일이 일어나고 있는지 설명해 주시겠습니까?
[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10
나는이 코드를보고 있지만 뇌는 숫자 10이 어떻게 결과가 될 수 있는지 등록하지 않습니다. 여기서 무슨 일이 일어나고 있는지 설명해 주시겠습니까?
답변:
첫 번째 블록 인수를 누산기로 생각할 수 있습니다. 블록의 각 실행 결과는 누산기에 저장되고 다음 블록 실행으로 전달됩니다. 위에 표시된 코드의 경우 누산기의 결과를 0으로 기본 설정합니다. 블록을 실행할 때마다 주어진 숫자가 현재 총계에 추가 된 다음 결과가 누산기에 다시 저장됩니다. 다음 블록 호출에는이 새로운 값이 있으며 추가하고 다시 저장 한 후 반복합니다.
프로세스가 끝나면 inject는 누산기를 반환합니다.이 경우 배열의 모든 값의 합 또는 10입니다.
다음은 문자열 표현으로 키가 지정된 객체 배열에서 해시를 만드는 간단한 예입니다.
[1,"a",Object.new,:hi].inject({}) do |hash, item|
hash[item.to_s] = item
hash
end
이 경우 누적기를 빈 해시로 기본 설정 한 다음 블록이 실행될 때마다 채워집니다. 블록의 결과는 누산기에 다시 저장되므로 블록의 마지막 줄로 해시를 반환해야합니다.
result + explanation
누산기로의 변환 및 반환 값입니다. 블록의 마지막 줄이므로 암시 적 반환입니다.
inject
( 0
예제에서) 로 시작하는 값 과 블록 을 취하고 목록의 각 요소마다 해당 블록을 한 번 실행합니다.
result + element
)을 저장합니다.이를 설명하는 가장 쉬운 방법은 예를 들어 각 단계의 작동 방식을 보여주는 것입니다. 다음은이 결과를 평가할 수있는 가상 단계입니다.
[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
inject 메소드의 구문은 다음과 같습니다.
inject (value_initial) { |result_memo, object| block }
위의 예를 해결해 봅시다.
[1, 2, 3, 4].inject(0) { |result, element| result + element }
출력으로 10 을 제공합니다 .
시작하기 전에 각 변수에 저장된 값이 무엇인지 살펴 보겠습니다.
결과 = 0 0은 inject (value) 에서 온 0입니다.
element = 1 배열의 첫 번째 요소입니다.
승인!!! 위의 예를 이해해 봅시다
1 단계 [1, 2, 3, 4].inject(0) { |0, 1| 0 + 1 }
2 단계 [1, 2, 3, 4].inject(0) { |1, 2| 1 + 2 }
단계 : 3 [1, 2, 3, 4].inject(0) { |3, 3| 3 + 3 }
단계 : 4 [1, 2, 3, 4].inject(0) { |6, 4| 6 + 4 }
단계 : 5 [1, 2, 3, 4].inject(0) { |10, Now no elements left in the array, so it'll return 10 from this step| }
여기서 굵은 기울임 꼴 값은 배열에서 가져온 요소이며 간단히 굵은 체 값이 결과 값입니다.
의 #inject
방법의 작동을 이해하기를 바랍니다 #ruby
.
그들이 말한 내용이지만 항상 "시작 값"을 제공 할 필요는 없습니다.
[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10
와 같다
[1, 2, 3, 4].inject { |result, element| result + element } # => 10
한번 해봐, 기다릴게
주입 할 인수가 전달되지 않으면 처음 두 요소가 첫 번째 반복으로 전달됩니다. 위의 예에서 결과는 1이고 요소는 2입니다. 따라서 블록에 대한 호출이 한 번 덜 이루어집니다.
tldr; 한 가지 중요한 방식 inject
과 다릅니다 . 블록의 마지막 실행 값을 반환하고 반복 된 배열을 반환합니다.map
inject
map
그보다 많은 각 블록 실행 값은 첫 번째 매개 변수 ( result
이 경우) 를 통해 다음 실행으로 전달되어 해당 값 ( (0)
부분)을 초기화 할 수 있습니다 .
위 예제는 다음 map
과 같이 쓸 수 있습니다 :
result = 0 # initialize result
[1, 2, 3, 4].map { |element| result += element }
# result => 10
동일한 효과이지만 inject
더 간결합니다.
map
블록 에서 할당이 수행 되는 반면 블록에서 평가가 수행되는 경우가 많습니다 inject
.
선택하는 방법은 원하는 범위에 따라 다릅니다 result
. 때 하지 가이 같은 것 사용
result = [1, 2, 3, 4].inject(0) { |x, element| x + element }
"Lookie me, 방금 모든 것을 한 줄로 결합했습니다"라고 생각할 수도 있지만 x
이미 result
작업 해야했기 때문에 필요하지 않은 스크래치 변수로 메모리를 임시로 할당 했습니다.
[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10
평범한 영어로, 당신은이 배열 ( [1,2,3,4]
)을 거치게 됩니다. 4 개의 요소 (1, 2, 3 및 4)가 있으므로이 배열을 4 번 반복합니다. inject 메소드에는 1 개의 인수 (숫자 0)가 있으며이 인수를 첫 번째 요소 (0 + 1)에 추가합니다. 1과 같습니다. 1은 "결과"에 저장됩니다. 그런 다음 해당 결과 (1)를 다음 요소 (1 + 2)에 추가합니다. 이것은 3입니다. 이것은 이제 결과로 저장됩니다. 3 + 3은 6과 같습니다. 마지막으로 6 + 4는 10과 같습니다.
여기서 시작한 다음 차단하는 모든 방법을 검토하십시오. http://ruby-doc.org/core-2.3.3/Enumerable.html#method-i-inject
당신을 혼란스럽게하는 블록입니까, 왜 메소드에 가치가 있습니까? 그래도 좋은 질문입니다. 거기에 연산자 방법은 무엇입니까?
result.+
무엇으로 시작합니까?
#inject(0)
우리는 이것을 할 수 있습니까?
[1, 2, 3, 4].inject(0) { |result, element| result.+ element }
이 작동합니까?
[1, 2, 3, 4].inject() { |result = 0, element| result.+ element }
당신은 단순히 배열의 모든 요소를 합산하고 문서에서 볼 수있는 메모에 숫자를 산출한다는 아이디어에 기초하고 있습니다.
당신은 항상 이것을 할 수 있습니다
[1, 2, 3, 4].each { |element| p element }
배열의 열거 가능한 항목이 반복되는지 확인하십시오. 이것이 기본 아이디어입니다.
주입하거나 줄이면 보내지는 메모 또는 누산기를 줄 수 있습니다.
우리는 결과를 얻을 수 있습니다
[1, 2, 3, 4].each { |result = 0, element| result + element }
그러나 아무것도 다시 나타나지 않으므로 이전과 동일하게 작동합니다.
[1, 2, 3, 4].each { |result = 0, element| p result + element }
요소 검사기 블록에서.
이것은 간단하고 이해하기 쉬운 설명입니다.
처음에는 다소 혼란 스럽기 때문에 "초기 값"은 잊어 버리십시오.
> [1,2,3,4].inject{|a,b| a+b}
=> 10
당신은 위와 같이 이해할 수 있습니다 : 1,2,3,4 사이에 "추가 기계"를 주입하고 있습니다. 즉, 1 ♫ 2 ♫ 3 ♫ 4이고 ♫는 추가 기계이므로 1 + 2 + 3 + 4와 동일하며 10입니다.
실제로 +
그들 사이에 a 를 삽입 할 수 있습니다 :
> [1,2,3,4].inject(:+)
=> 10
마치 +
1,2,3,4 사이에 a 를 삽입하여 1 + 2 + 3 + 4로 만들고 10으로 만듭니다. 이것은 :+
루비 +
가 기호 형태로 지정하는 방식입니다 .
이것은 이해하기 쉽고 직관적입니다. 그리고 단계별로 작동하는 방식을 분석하려면 다음과 같습니다 .1과 2를 가져 와서 추가하고 결과가있을 때 먼저 저장하고 (3) 저장하고 다음은 저장됩니다 값 3과 배열 요소 3은 6 인 a + b 프로세스를 거치고 이제이 값을 저장하고 이제 6과 4는 a + b 프로세스를 거치고 10입니다.
((1 + 2) + 3) + 4
"초기 값" 0
은 시작하기위한 "기본"일뿐입니다. 많은 경우에 필요하지 않습니다. 1 * 2 * 3 * 4가 필요하다고 상상해보십시오.
[1,2,3,4].inject(:*)
=> 24
그리고 그것은 끝났습니다. 1
전체를에 곱하기 위해 "초기 값"이 필요하지 않습니다 1
.
.inject () 메소드의 또 다른 형태가 있습니다. [4,5] .inject (& : +)이 부분의 모든 요소를 더할 것입니다