์˜ค๋Š˜์€ ์ž‘์—… ์ค‘ ๋‚ด๊ฐ€ ๋ชจ๋ฅด๋Š” ์ฝ”๋“œ๋ฅผ ๋ฐœ๊ฒฌํ•ด์„œ ๊ธ€์„ ์จ๋ณธ๋‹ค. reduce! reduce(::) ํ˜•ํƒœ๋งŒ ๋ด์™”์—ˆ๋Š”๋ฐ reduce(into::) ํ˜•ํƒœ๋„ ์žˆ๋”๋ผ! ์•Œ์•„๋ณด์ž.

reduce(::)

Returns the result of combining the elements of the sequence using the given closure. ์ฃผ์–ด์ง„ ํด๋กœ์ €๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹œํ€€์Šค์˜ ์š”์†Œ๋ฅผ ์กฐํ•ฉํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
  • intialResult
    • ์ดˆ๊ธฐ๊ฐ’์ด๋‹ค. ์ˆ˜์—ด์—์„œ ์ฒซ์งธํ•ญ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋˜๊ฒ ๋‹ค.
  • nextPartialResult
    • ์ด์ „์˜ ๊ฒฐ๊ณผ๊ฐ’, ๊ทธ๋ฆฌ๊ณ  Sequence์—์„œ ๋‹ค์Œ ๊ฐ’์„ input์œผ๋กœ ๊ฐ–๋Š” ํด๋กœ์ €๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ณณ์ด๋‹ค.

์˜ˆ์ œ

let numbers = [1, 2, 3, 4]
let numberSum = numbers.reduce(0, { x, y in
    x + y
})
// numberSum == 10
  • ์ฒ˜์Œ์—๋Š” x์— 0์ด ๋“ค์–ด์˜ค๊ณ , y์— 1์ด ๋“ค์–ด์˜จ๋‹ค.
  • ๋‹ค์Œ์—๋Š” ๋”ํ•œ ๊ฒฐ๊ณผ์ธ x์— 1์ด ๋“ค์–ด์˜ค๊ณ  y์—๋Š” 2๊ฐ€ ๋“ค์–ด์˜จ๋‹ค.
  • ์ด์™€ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ sequence์˜ ๋๊นŒ์ง€ ๋‹ฌ๋ฆฐ๋‹ค.
  • ๋‹น์—ฐํ•˜๊ฒŒ๋„ ์‹œ๊ฐ„๋ณต์žก๋„๋Š” O(n)์ด๋‹ค.

reduce(into:_:)

This method is preferred over reduce(::) for efficiency when the result is a copy-on-write type, for example an Array or a Dictionary. ๊ฒฐ๊ณผ๊ฐ€ copy-on-write์ธ, ์ฆ‰ Array, Dictionary์™€ ๊ฐ™์€ ๋…€์„, ์นœ๊ตฌ๋“ค์ผ ๋•Œ ์ข‹์€ ๋ฉ”์„œ๋“œ!

func reduce<Result>(into initialResult: Result, _ updateAccumulatingResult: (inout Result, Element) throws -> ()) rethrows -> Result
  • initialResult
    • ์ดˆ๊ธฐ๊ฐ’
  • updateAccumulatingResult
    • sequence์˜ ์›์†Œ๋ฅผ ๊ฐ€์ง€๊ณ  ๊ฐ’์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ํด๋กœ์ €
    • ํ•ต์‹ฌ์€ inout!!!

์—ฌ๊ธฐ์„œ ์œ„์˜ reduce(_:_:)์™€ reduce(into:_:)์˜ ์ฐจ์ด์ ์ด ๋ณด์ธ๋‹ค. ํ›„์ž์˜ ๊ฒฝ์šฐ ํด๋กœ์ € ๋ณ€์ˆ˜๋กœ inout ํ‚ค์›Œ๋“œ๊ฐ€ ๋ถ™์–ด์žˆ๋Š” ์ •๋ณด๊ฐ€ ๋“ค์–ด์˜จ๋‹ค. ๋ฌด์Šจ ์ฐจ์ด์ผ๊นŒ?

inout ํ‚ค์›Œ๋“œ๊ฐ€ ์–ด๋ ต๋‹ค๋ฉด, ํ•ด๋‹น ํฌ์ŠคํŒ…์„ ์ฝ๊ณ  ์˜ค์ž. ๊ฐ„๋‹จํ•˜๊ฒŒ ์–˜๊ธฐํ•˜๋ฉด, ์ผ๋‹จ ๊ธฐ๋ณธ์ ์œผ๋กœ closure์˜ ์ธ์ž๋กœ ๋“ค์–ด๊ฐ„ ๋ณ€์ˆ˜๋Š” copy๋œ๋‹ค. ๋”ฐ๋ผ์„œ closure ๋‚ด๋ถ€์—์„œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋”๋ผ๋„, ํ•ด๋‹น ํด๋กœ์ € ์™ธ๋ถ€์˜ ๋ณ€์ˆ˜๋Š” ๋ณ€ํ•จ์ด ์—†๋‹ค. (Immutable)

ํ•˜์ง€๋งŒ inout ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ์™ธ๋ถ€์—์„œ ๋„ฃ์–ด์ค€ ๋ณ€์ˆ˜ ์ฃผ์†Œ ๊ทธ๋Œ€๋กœ ๋ฐ˜์˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ๊ฐ’์„ ์กฐ์ž‘ํ–ˆ์„ ๊ฒฝ์šฐ, ํ•ด๋‹น ๊ฒฐ๊ณผ๊ฐ€ ๊ทธ๋Œ€๋กœ ๋‚จ์•„์žˆ๋‹ค. (Mutable)

๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ค ๊ฒฝ์šฐ๋ฅผ ์ƒ๊ฐํ•˜๊ณ  ๋งŒ๋“  ๊ฒƒ์ด๋ƒ! ๋ฐ”๋กœ ์ดˆ๊ธฐ๊ฐ’์ด ๋ฐฐ์—ด, ๋”•์…”๋„ˆ๋ฆฌ๋กœ ๋“ค์–ด์˜จ ๊ฒฝ์šฐ, ํ•ด๋‹น ๋ฐฐ์—ด์ž์ฒด์— ๊ฐ’์„ ๋ณ€๊ฒฝํ•ด์ฃผ๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ๋ง์ด ์–ด๋ ต๋‹ค. ์˜ˆ๋กœ ์•Œ์•„๋ณด์ž!

์˜ˆ์ œ

let letters = "abracadabra"
let letterCount = letters.reduce(into: [:]) { counts, letter in
    counts[letter, default: 0] += 1
}
// letterCount == ["a": 5, "b": 2, "r": 2, "c": 1, "d": 1]

์ด ์˜ˆ์ œ๋Š”, ํŠน์ • ๋ฌธ์ž์—ด ์•ˆ์—์„œ ๊ฐœ์ˆ˜๋ฅผ ํŒŒ์•…ํ•˜๊ธฐ ์œ„ํ•œ ์ฝ”๋“œ์ด๋‹ค. ์ดˆ๊ธฐ๊ฐ’์ด dictionary๋กœ ๋“ค์–ด๊ฐ”๊ณ , ํ•ด๋‹น ์ดˆ๊ธฐ๊ฐ’ ์ž์ฒด๋ฅผ ์ง์ ‘์ ์œผ๋กœ ๋ณ€๊ฒฝํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ณ  ์‹ถ์–ดํ•œ๋‹ค. ๋งŒ์•ฝ ์ด ์ƒํ™ฉ์—์„œ reduce(into:_:) ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ์–ด๋–จ๊นŒ? For ๋ฌธ์„ ๋Œ๋“ , ForEach๋กœ ๋Œ๋“  ๊ฒฐ๊ตญ ๋Œ์•„์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ํ–ˆ์„ ๊ฒƒ์ด๋‹ค.

์ •๋ฆฌ

ํ•ต์‹ฌ์€ inout์ด๋‹ค! ์ดˆ๊ธฐ๊ฐ’์œผ๋กœ ๋„˜๊ธฐ๋Š” ์ธ์ž์ž์ฒด์— ๋ฌด์–ธ๊ฐ€ ๋ณ€ํ˜•์„ ๊ฐ€ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์—ฌ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ณ  ์‹ถ๋‹ค๋ฉด reduce(into:_:) ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ํŠนํžˆ ๊ทธ ์ดˆ๊ธฐ๊ฐ’์ด ๋”•์…”๋„ˆ๋ฆฌ, ๋ฐฐ์—ด์ธ ๊ฒฝ์šฐ๊ฐ€ ์œ ์šฉํ•˜๊ฒ ๋‹ค. ์•„๋ฌด๋ž˜๋„ ํŠน์ • ๊ฐ’์ธ ๊ฒฝ์šฐ๋Š” ํด๋กœ์ €๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ˆœ์ˆ˜ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•  ์ผ์ด ์—†์œผ๋‹ˆ๊นŒ.

Reference