Collection Iteration with Closure : Mr. closure์ ํจ๊ปํ๋, ์ปฌ๋ ์ ์ดํฐ๋ ์ด์
์ผ๋ จ์ ํ๋ก์์ ธ๋ฅผ ์ฌ์ฌ์ฉํ๋, func์ด์ธ์ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด ๋๋ ...
ํนํ, ์ปฌ๋ ์ ๋ค์ ๋ค๋ฃฐ ๋ ํนํ ์ ์ฉํ ...
๋ณ์์ ํ ๋นํด, ๋ค๋ฅธ value๋ค ์ฒ๋ผ "์ฃผ๊ณ ๋ฐ์ ์ ์๋" ...
๊ทธ ๋ถ ...
์ด๋ฆ ์๋ ํจ์ ...
Mr. closure๋ฅผ ์๊ฐํฉ๋๋ค.
์ฐธ๊ณ : Raywenderlich
"Swift Apprentice"
https://store.raywenderlich.com/products/swift-apprentice
Closure Basics ํด๋ก์ ์ฉ๊ธฐ์ด + training
ํด๋ก์ ธ๋ ๋๋ฌ์ผ ํ๊ฒฝ์ ๋ณ์๋ ์์๋ฅผ ์์ ์ scope์ผ๋ก "close over"ํ ์ ์์ด์, ํด๋ก์ ๋ผ๋ ์ด๋ฆ์ด ๋ง๋ค์ด์ก์ต๋๋ค. ์ด close over vars. and consts. ๋ captureํ๋ค๊ณ ๋ ํ๋ ๋ฐ ์ถํ์ ์์ธํ ์ค๋ช ํด๋๋ฆฌ๊ฒ ์ต๋๋ค. ์ง๊ธ์ ๊ฑ ์์ผ์ธ์ ^^ ์์ด๋ก๋ง ์จ์ ์ฃ์กํด์. ์ง๋๋ก ์ค๋ช ํ๋ ๋ถ๋ถ์๋ ์์ฐ๋ฆฌ๋ง๋ก ์ง๋๋ก ์ฐ๊ฒ ์ต๋๋ค.
----> 1). ์ด๋ป๊ฒ ๋ง๋๋์?
var multiplyClosure: (Int, Int) -> Int
์ฐ์ , ํด๋ก์ ๋ฅผ ๋ด์ ๋ณ์๋, ๋ค์๊ณผ ๊ฐ์ด ํ์์ ๋ช ์ํ ์ ์์ต๋๋ค. ํจ์๋ฅผ ์ฃผ๊ณ ๋ฐ์ ๋์ ๋์ผํ์ฃ .
----> 2). ๊ฐ์ ์ด๋ป๊ฒ assign ํ๋ ๋ฐ์?
---- ----> 1. ํ์คํ
// ํ์ ๋ช
์ ์์ ๋,ํ์ ์ถ๋ก ํ๋ ๊ฒ๋ ์ ๋ณด์ธ์ ^^
var multiplyClosure = { (a: Int, b: Int) -> Int in
return a*b
}
// ์ฌ์ฉ
let result = multiplyClosure(4, 2)
ํจ์ ์ ์ธํ ๋๋, ์ข ๋ค๋ฅธ ์ ์ด๋ผ๋ฉด ์ ๋ ฅ์ ๋ํด ๋ช ์ํ ๋, _ a: Int, by b: Int ์ ๊ฐ์ด ํจ์์ ์ ๋ ฅ์ external argument label ์ธ๋ถ์์ ์ธ์๋ฅผ ์ง์นญํ๋ ์ธ๋ถ ๋ผ๋ฒจ ๋ฐ์๋ ์์ต๋๋ค. ํด๋ก์ ์์ฒด๊ฐ ๊ฐํธํ ํจ์ ์ ๋ฌ์ด ๋ชฉ์ ์ด๋ ์ต๋ํ ๊ฐ๋ณ๊ฒ ํด์ผ์ฅฌ. ๊ทธ๊ฑด ์ค์ํํธ ์ธ์ด ๋์์ด๋ ๋งด์ ๋๋ค. ์ ํฌ๋ ๊ทธ์ ๋ฐ๋ฅผ๋ฟ.
์ด์ฉ ๋ฐฉ๋ฒ์ ๊ทธ๋ฅ ํจ์์ ๋์ผํฉ๋๋ค. ํด๋ก์ ธ๋ช (์ ๋ ฅ1, ์ ๋ ฅ2, ... ํ์ํ ๋งจํผ)
----> 3). Shorthand syntax ์ถ์ฝ๋ ํด๋ก์ ๋ฌธ๋ฒ๋ค
์ ํ ๋ฌธ์๋ณผ ๋ ์์๊ฒ ์ง๋ง, ๋ค๋ฅธ ์ธ์ด๋ฅผ ์ฐ๋ค ์ค์ํํธ ๋ํ๋จผํธ๋ฅผ ๋ณด๋ฉด, ์ ํ ํ ์ ์ผ๋ก ๋ฐ๊พธ๊ณ ์ค์ฌ๋์ ์ ํ์ค์ ๋ญ๊ฐ ์ฌ์คํด๋ณด์ด๋ ์ข์ ๊ฐ์ ๋ฐ๊ณคํฉ๋๋ค. ๊ทธ๋ ๊ธฐ์, syntax๊ฐ ๋ญ๊ฐ ์ค์ํด? ๊ฑ ์๊ณ ๋ฆฌ์ฆ์ด ์ค์ํ์ง --> ๋ฏธ๋์ ๋ด ๋๊ณผ ๋๋ฅผ ์ํด ์ ํ์ค ์ง์์ ์ ๋ฌผํ ๊ฒ ๋ผ๋ ๋ง์ธ๋๋ก ๊ณต๋ถํด๋ณด๋ ๊ฒ ๋์์ง ์์๋ณด์ ๋๋ค. AI AI AI !! ์๋๊ณ syntax, syntax, syntax !!
์๋์ ๊ฐ์ด ์ ํ์ค๋ฅผ ๋ง๋ ๋ฐ๋ ๋ณ๋ค๋ฅธ ์ด์ ๊ฐ ์์ต๋๋ค -> ์ ํ์ค๋ฝ๊ฒ, ๊ฐ์ ๋ช ๋ น์ ์ด๋ป๊ฒ ํ๋ฉด ์ต๋ํ ์ ๊ฒ ํ์ดํํ๋ฉด์๋ ๋ช ๋ฃํ๊ฒ ๋ง๋ค ๊นํ๋ค๊ฐ ๋ง๋ค์ด์ง ๊ฒ์ผ ๊ฒ์ ๋๋ค.
1). ํ๋ผ๋ฏธํฐ ๋ฆฌ์คํธ: ์ ์ง, ๋ฆฌํด ํ์: ์ ์ง, inํค์๋: ์ ์ง, returnํค์๋: ์๋ต : ๋ฆฌํดํ ํญ๋ชฉ์ ํ ์ค ์ด๋ด์ ์ ๋ฌํ ์ ์๋ค๋ฉด, ๊ทธ๊ฒ๋ง ์จ๋ ์ปดํ์ผ๋ฌ๊ฐ ์์์ ์ปดํ์ผ ํด์ค๋๋ค.
multiplyClosure = { (a: Int, b: Int) -> Int in
a * b
}
2). ํ๋ผ๋ฏธํฐ ๋ฆฌ์คํธ: ์ธํฐ๋ ๋ผ๋ฒจ๋ง ์ ์ง, ๋ฆฌํด ํ์: ์๋ต, inํค์๋: ์ ์ง, returnํค์๋: ์๋ต
/ * ์ด๋ฏธ ํ์ ์ธ์ ์ผ๋ก ๋ช
์ํ ๊ฒฝ์ฐ๊ฐ ์์ ๊ฒฝ์ฐ
var multiplyClosure = { (a: Int, b: Int) -> Int in
return a*b
}
*/
// ๊ฐ๋ตํ๊ฒ ์ฌ์ง์ ํด์ฃผ๊ธฐ (์ด๋ฆ1, ์ด๋ฆ2) in ์ด๋ฆ1 * ์ด๋ฆ2
multiplyClosure = { (a, b) in
a * b
}
3). ํ๋ผ๋ฏธํฐ ๋ฆฌ์คํธ: ์๋ต, ๋ฆฌํด ํ์: ์๋ต, inํค์๋: ์๋ต, returnํค์๋: ์๋ต : + ์ ๋ ฅ ์ธ์๋ฅผ $0, $1๋ก ์ง์นญ
์ด ์ ํ์ค๋ ์์ฃผ ์ฐ์ด๋ !! ์ ํ์ค ! ์ ํ์ค! ์ ํ์ค! ํ ๋ฒ ํ์ดํ ํด๋ณด์๋ฉด์ ์ตํ์๋ฉด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค.
// pass function as a parametre
func operateOnNumbers(_ a: Int, _ b: Int, operation: (Int, Int) -> Int ) -> Int {
let result = operation(a, b)
print(result)
return result
}
// ํด๋ก์ ธ๋ฅผ ์ธ์๋ก ์ ๋ฌ
operateOnNumbers(4, 2, operation: { $0 + $1 })
์์ ํจ์๋ operation ์ธ์๋ก (Int, Int) -> Int ๋ผ๋ ํจ์ ๋๋ ํด๋ก์ (์ด๋ฆ ์๋ ํจ์)๋ฅผ ๋ฐ์ต๋๋ค. ์ด๋ฌํ ์ํฉ์, ํด๋ก์ ๋ฅผ ์ ๋ฌํด์ฃผ์๋ฉด ๋ฉ๋๋ค. ์์์๋ ์ฒซ ๋ฒ์งธ ์ธ์์, ๋ ๋ฒ์งธ ์ธ์๋ฅผ ๋ํ ๊ฐ์ ๋ฆฌํดํ๋ค๋ ํด๋ก์ ธ๋ฅผ ์ธ์๋ก ์ ๋ฌํ์๊ณ , ์ ํฌ๊ฐ ์ด๋ฏธ ์์์ ํจ์๋ฅผ ์ ์ํ ๋, ํ์์ ๋ํด์๋ ์ด๋ฐ ์ด๋ฐ ์ธํ์ด ๋ค์ด์ฌ ๊ฒ์ด๋ค๋ผ๋ ๊ฒ์ ๋ช ์ํด ๋์๊ธฐ ๋๋ฌธ์, operation์ธ์๋ก,
ํ์์ด ๋ช ์๋์ง ์์
params list, in keyword, return ๋ฑ์ด ์๋ต๋
ํด๋ก์ ๋ฅผ ์ ๋ฌํด๋, ์ปดํ์ผ๋ฌ๊ฐ ํจ์๋ฅผ ์ถ๋ก ํด๋ผ ์ ์์ต๋๋ค.
Trailing Closure Syntax
์ค์ํํธ๋ฅผ ๋ณด๋ฉด, ๋งค์ฐ ์ด์ํ ํ์์ ํจ์ ํธ์ถ์ ๋ณผ ์ ์๋๋ฐ,
์ฌ๊ธฐ์ "trailing closure syntax"์ ๋ํด์ ์ด์ผ๊ธฐ ํด๋ณด๋ ค ํ๋ค.
์์์๋ " operation: ์ด๋ผ๋ ์ธ์์ { $0 + $1 } ๋ผ๋ ํด๋ก์ ธ๋ฅผ ์ ๋ฌ"ํ๋ ๋ฐฉ์์ผ๋ก ํด๋ก์ ธ๋ฅผ ํธ์ถํ๋๋ฐ,
์ค์ํํธ๋ ๋ง์ฝ, ์ธ์ ์ค ๋ง์ง๋ง์ด ํจ์๋ฅผ ๋ฐ๋ ๊ฒฝ์ฐ์๋, ๋ ๋ ๋ ๊ฐ๋จํ ์ ํ์ค๋ฅผ ์จ์, ๊ฐ์ ๋ฐฉ์์ผ๋ก ํจ์๋ฅผ ํธ์ถํ ์ ์๊ฒ ํด์ค๋ค.
operateOnNumbers(4,2){
$0 + $1
}
* ๋ง์ฝ, ์ด๋ค ํจ์์ ๋ง์ง๋ง ์ธ์๊ฐ ํจ์๋ผ๋ฉด, 1). ์ธ์ ๋ผ๋ฒจ์ ์๋ตํ๊ณ , ๋ค์๊ณผ ๊ฐ์ด ์์ 2). ( ) ๋ฐ์ ํด๋ก์ ธ๋ฅผ ํํํ๋trailing ๋ฐฉ์์ผ๋ก ์ ๋ฌํ ์ ์์ต๋๋ค. ๋งค์ฐ ์์ ( ) parenthesis ์์ ์ ๋ฌํ๋ ๊ฒ๋ณด๋ค, ์์ ๊ธธ์ด์ง ์ ์๋ ํด๋ก์ ธ๊ฐ ๋ค์ด๊ฐ๋ ๊ฒฝ์ฐ๋ ( )์ trailing(ํํํ๋) ์ ๋ฌ ๋ฐฉ์์ ์ฌ์ฉํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฒ์ผ๋ก ๋ณด์ ๋๋ค.
empty params list and empty return
let voidClosure2: () -> Void = {
print("Swift is so awesome")
}
// also possible
let voidClosure3: () -> () = {
print("Swift is so awsome")
}
๋ง์ฝ, ์ค์ํํธ๊ฐ ๋งค๊ฐ๋ณ์๊ฐ ํ์ ์๊ฑฐ๋, ์๋ฌด ๊ฒ๋ ๋ฆฌํดํ์ง ์๋๋ค๋ฉด ์์ ๊ฐ์ ๋ ๊ฐ์ง ์ต์ ์ด ์์ต๋๋ค. ํจ์์ ํํ์
ํ์์ ๋ช ์ํด์ฃผ์ด์ผํ๋๋ฐ, ( ) -> Void ๋๋ -> ( )์ ๊ฐ์ด ๋ช ์ํด์ฃผ๋ฉด ๋ฉ๋๋ค.
----> 4). Closure Capture : < capture variables from enclosing scope >
ํด๋ก์ ๋ ๊ทธ๊ฒ์ ๋๋ฌ์ผ ํ๊ฒฝ์ ์๋ entities(๋ณ์, ์์)๋ฅผ ์บก์ณํด์, ์์ ํ ์ ์์ต๋๋ค. ์ฆ, ํด๋ก์ ๊ฐ ์ ์๋ ๊ฒ์ ๋๋ฌ์์ ์ธ๋ถ ํ๊ฒฝ์ ๋ณ์๋ ์์์ scope์ ํด๋ก์ ๋ด๋ถ๋ ํฌํจ๋๋ค๋ ๊ฒ์ ๋๋ค.
func countingClosure() -> () -> Int {
// ๋ก์ปฌ ๋ณ์
var counter = 0
// ํจ์์ ๋ก์ปฌ ๋ณ์๋ฅผ ์บก์ณํ๋ ํด๋ก์ ธ, ๊ทธ ๊ฒ์ +1์ ํ๊ณ ๋ฆฌํด ํ๋ค
let incrementCounter: ( ) -> Int = {
counter += 1
return counter // ์์ ํ๋ก์์ ธ๋ฅผ ์งํํ๊ณ counter๋ฅผ ๋ฆฌํดํ๋ค.
}
// ๊ทธ๋ ๊ฒ ์บก์ณํด์, +1์ํ๊ณ ๋ฆฌํดํด์ค๋ค๋ ์ธํฌ๋ฆฌ๋จผํธ ์นด์ดํฐ "ํด๋ก์ ธ๋ฅผ ๋ฆฌํด"
return incrementCounter
}
//
counter1 = countingClosure()
counter2 = countingClosure()
counter1( ) // 1
counter1( ) // 2
counter2( ) // 1
counter2( ) // 2
surrounding environment's entities๋ฅผ captureํ๋ค๋ ๊ฒ์ ๋ฌด์จ ๋ป์ผ๊น์? ์บก์ณ๋ผ๋ ๊ฒ ์ด๋ค ๊ฒ์ ํฌ์ฐฉํด์ ๊ฐ์ง๊ณ ์๋ ๋ค๋ ๋ป์ด์ฃ ? ์ ํฌ๋ ์ ํฌ๋ธ ๋์์์ ํ ์๊ฐ์ ์บก์ณํด์ ๊ฐ์ง๊ณ ์๊ฒ๋ฉ๋๋ค. ํด๋ก์ ธ์ ์บก์ณ๋ ๋น์ทํ ๊ฐ๋ ์ผ๋ก ์๋ํฉ๋๋ค.
์์์ ๋ณด๋ฉด, countingClosureํจ์๋ฅผ ํธ์ถํ๋ฉด, ๋ก์ปฌ ๋ณ์์ธ counter๊ฐ ์์ฑ๋๊ณ , incrementCounter๋ผ๋ ํด๋ก์ ธ๋ ๊ทธ ๋ ์์ฑ๋ ๋ก์ปฌ ๋ณ์๋ฅผ ์บก์ณํด๋์ต๋๋ค. ์ด๋ ์ด ํด๋ก์ ธ๋ ์ด ๋ก์ปฌ ๋ณ์๋ฅผ "๋ ํผ๋ฐ์ค" ๋ณ์ ํ ํฉ๋๋ค. ๊ทธ ๊ฐ์ ํ ๋ฉ๋ชจ๋ฆฌ๋ก ์ฎ๊ฒจ, ๊ทธ๊ฒ์ ๋ํ ๋ ํผ๋ฐ์ค๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ, ๊ทธ๊ฒ์ counter๋ผ๊ณ ๋ถ๋ฅด๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ ๊ฒ counter๋ผ๋ ํ ๋ฉ๋ชจ๋ฆฌ ์ ๋ฐ์ดํฐ์ ๋ํ ๋ ํผ๋ฐ์ค๋ฅผ ์บก์ณํด๋ธ ํด๋ก์ ธ๊ฐ ๋ฆฌํด๋๋ ๋ฐ, ์ด๋ ๋ง์ฝ counter๊ฐ ํจ์์ ๋ก์ปฌ ๋ณ์์์ผ๋ฉด, save๋์ง ์์ ์ ์ง๋ ์ ์์ต๋๋ค. ํ์ง๋ง, ํด๋ก์ ธ๋ ๊ทธ๊ฒ์ ํ์ ์ ์ฅํด counter๋ผ๋ ์ด๋ฆ์ผ๋ก ๊ฐ์ง๊ณ ์์ผ๋ฉด, ํด๋ก์ ธ๊ฐ ํด๋น ๋ฐ์ดํฐ์ ๋ํ ๋ ํผ๋ฐ์ค๋ฅผ ์ ์งํ๊ธฐ ๋๋ฌธ์ ์ง์์ง์ง ์์ต๋๋ค.
์ฒซ ๋ฒ์งธ ์นด์ดํ ํด๋ก์ ธ( )๋ฅผ ํธ์ถํ๋ฉด, ๊ทธ๋ ์นด์ดํฐ ๋ณ์๋ฅผ ์บก์ณํ์ฌ ๋ ํผ๋ฐ์ค๋ฅผ ๊ฐ์ง๊ณ ์๋ ํด๋ก์ ธ์ธ counter1 ์ด ์๊น๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋๋ฒ์งธ ํธ์ถํ ๋๋ ๋ ๊ทธ๋ ์์ฑ๋์ด ํ์ ์ ์ฅ๋ ๋ ํผ๋ฐ์ค counter๊ฐ ์๊น๋๋ค. ๊ฐ ํด๋ก์ ๋ด์์๋ ํ ๋ฉ๋ชจ๋ฆฌ ์์ ๋ค๋ฅธ ์์น์ ๋ํด ๊ฐ์ ์ด๋ฆ์ ๋ ํผ๋ฐ์ค ๋ณ์๋ฅผ ๊ฐ์ง๊ฒ ๋ฉ๋๋ค.
๊ฐ๊ฐ ์๋ก ๋ค๋ฅธ ์์น์ ํ ๋ฉ๋ชจ๋ฆฌ์ ๋ฐ์ดํฐ, ๋๋ช ์ ๋ค๋ฅธ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ฐ +1 +1 ํ๋ฉด์ ๋ฆฌํดํด์ฃผ๊ณ ์์ต๋๋ค.
์บก์ณ๋ผ๋ ๊ฒ์ ๊ฐ๋ ์ด ์๋ฟ์ง ์์ ์ข์ ๋ธ๋ก๊ทธ ๊ธ์ ์ฐธ๊ณ ํ์ฌ ์ดํดํ๊ฒ๋์ด, ์ด ๊ธ์ ๊ณต์ ํฉ๋๋ค. ๊ฐ์ฌํฉ๋๋ค. ์ถ์ฒ :
>>> Human is pattern making pro !!
>>> ์ฐ์ตํด ๋ด ์๋ค : ์ด๋ฒ์๋ ํด๋ก์ ๊ฐ, ์์ ์ด ์ ์๋๊ณ ์๋ ํจ์ ํ๋ก์์ ๋ด์์,
- ํ๋ผ๋ฏธํฐ
- ์ง์ญ๋ณ์
๋ชจ๋๋ฅผ ์บก์ณํด์ ์ ์งํฉ๋๋ค.
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0 // local ๋ณ์๋ฅผ ๋งค๊น => ์บก์ณํด์ => ํ์ผ๋ก ์ฎ๊ฒจ์ ํด๋น ์ง์นญ์ ์ ์งํ๋ ํด๋ก์
let incrementer = { ( ) -> Int in
runningTotal += amount // ํ๋ผ๋ฏธํฐ์ธ amount ์บก์ณํด์ ๋ ํผ๋ฐ์ค ์ ์ง, runningTotal๋ ์ฐฐ์นต!!
return runningTotal
}
return incrementer
}
let incrementer5 = makeIncrementer(forIncrement: 5)
let incrementer10 = makeIncrementer(forIncrement: 10)
incrementer5( ) // 5
incrementer10( ) // 10
incrementer5( ) // 10
incrementer10( ) // 20
incrementer5( ) // 15
incrementer10( ) // 30
----> 5). Easy collections control using: Closure
์ด์ , ํด๋ก์ ๋ฅผ ๋ฐฐ์ด ๊ฒ์ ๋๋ ค๋ด ์๋ค. ๊ฐ์ฅ ์ ์ฉํ ๋ฐฉํฅ์ ๋ฐ๋ก, ์ปฌ๋ ์ ์ ๊ฐ๊ฒฐํ๊ฒ ๊ฐ์ง๊ณ ๋๊ธฐ. Too Swift !!
ํด๋ก์ ธ์ ์ ํ์ค๋ฅผ ์๋ฉด, ์ค์ํํธ์ ์ปฌ๋ ์ ํ์๋ค์ ๋งค์ฐ ๊ฐ๋จํ ํํ๋ก ํต์ ํ ์ ์๋, ์ปฌ๋ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๊ฐ์ถ์ด์ ธ ์์ต๋๋ค. "ํจ์ํ ํ๋ก๊ทธ๋๋ฐ"์ ์งํฅํ๋ ์ค์ํํธ์์๋, ์ปฌ๋ ์ ์คํผ๋ ์ด์ ์ ์ธ์๋ก์ "ํด๋ก์ ธ"๋ฅผ ์ ๋ฌํ๋ ๋ฐฉ์์ผ๋ก ์๋ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง๊ณ , ์ด๋ closure trailing syntax๋ฅผ ์ฌ์ฉํ๋ฉด, ์ด๋ฌํ ๊ฒ๋ค์ด ์ ํ์ค์ ์ผ๋ก ๋งค์ฐ ๊ฐ๋จํ๊ฒ ํด๊ฒฐ ๊ฐ๋ฅํ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค.
1). ์ ๋ ฌ ๋ฌธ์ ํด๊ฒฐ
let names = [ "zebra", "boeing", "ace", "create", "eastern"]
// ์ฒซ ๋ฒ์งธ ์๊ท๋จผํธ๊ฐ ๋ ์ปค์ผํด
1).
names.sorted{
$0.count > $1.count
}
// ์ฒซ ๋ฒ์งธ ์๊ท๋จผํธ๊ฐ ๋ ์์์ผํด
2).
names.sorted{
$0.count < $1.count
}
// ๋ํ๋จผํธ ์ฐธ๊ณ
// ์ธ์ ์ค๋ช
// areInIncreasingOrder :
// A predicate that returns true if its first argument
// should be ordered before its second argument; otherwise, false.
์ ์ ์กฐ๊ฑด : ํจ์๋ ํด๋ก์ ๋ฅผ ์ ๋ฌํด๋ผ. ๋ง์ฝ ์ฐธ์ผ ๊ฒฝ์ฐ, ์ฒซ๋ฒ์งธ ์ธ์๊ฐ ๋๋ฒ์งธ ์ธ์์ ์์ผ๋ก ๊ฐ์ผํ๋ ํจ์. ์ฆ ์ ๋ ฌ์ ์กฐ๊ฑด์ธ ( ์ , ์ ) -> ๋ถ ํด๋ก์
2). Iterative operation : ์ปฌ๋ ์ ์ ๊ฐ ์์๋ฅผ ์ดํฐ๋ ์ด์ ํ๋ฉด์, ํด๋ก์ ์ ์ ์ํ ํ๋ก์์ ธ๋ฅผ ์คํ
1). ์ดํฐ๋ ์ด์ ํ๋ฉฐ ๊ฐ ์์์ ๋ํด ํ๋ก์์ ธ ์ํ : forEach
let values = [1, 2, 3, 4, 5, 6, 8, 9]
values.forEach{
print("\($0): \($0*$0)")
}
// ์ปฌ๋ ์
์ ๊ฐ ์์๋ฅผ ์ดํฐ๋ ์ด์
ํ๋ฉฐ, ๊ฐ ์์์ ๋ํด ๋ค์์ ์คํ
2). ํํฐ๋ง : ๊ฐ ์์์ ๋ถ๋ฆฐ ํ ์คํธ ํ์ฌ ํํฐ๋งํ์ฌ true์ธ ๊ฒ๋ง ๋ฆฌํด
var prices = [ 1.5, 10, 4.99, 2.30, 8.19 ]
let largePrices = prices.filter{
$0 > 5
}
// original : ๋ฉ์๋๊ฐ ์ ์ฉ๋๋ ์ด๋ ์ด์ ๊ฐ๋ค์ ํ์ Double, -> [Double]
func filter( _ isIncluded: (Element) -> Bool ) -> [ Element ]
let sucky = ["hi", "hilary", "dylan", "friendly", "dude"]
sucky.filter{
$0.count > 4
}
.filter( ) ํจ์๋ ๋ํ๋จผํธ ์
์ปฌ๋ ์ ๋ฐ์ดํฐ ํ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ -> ๋ถ๋ฆฌ์ธ ๊ฐ์ ๊ณ์ฐํ๋ ํด๋ก์ ธ๋ ํจ์๋ฅผ ๋ฐ์, ์ปฌ๋ ์ ๋ฐ์ดํฐ ํ์์ ํด๋นํ๋ ๊ฐ์ ๋ด์ด๋๋,
ํด๋ก์ ธ์ ๋ฆฌํด๊ฐ์ด ํธ๋ฃจ์ธ ์์๋ค๋ง ๊ฑธ๋ฌ๋ด๋ ํจ์์ ๋๋ค.
3). ํํฐ๋ง : ์ค์ง ์ฒซ๋ฒ์งธ ์์
print( prices.first{
$0 > 5
} ?? 0 )
let sucky = ["hi", "hilary", "dylan", "friendly", "dude"]
sucky.filter{
$0.count > 12
}
var result: String
let over10 = sucky.first(where: {$0.count > 10}) ?? "no such member"
over10
์์ ํจ์๋ฅผ ๋ณด๋ฉด, predicate๋ผ๋ ํจ๋ฌ๋ฏธํฐ๋ฅผ where๋ผ๋ ์๊ท๋จผํธ ๋ผ๋ฒจ๋ก ๋ฐ๊ณ ์๋๋ฐ, ํจ๋ฌ๋ฏธํฐ๋ ํด๋ก์ ธ๋ก ๋ฐ๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. ๋๋ธ์ ๋ฐ์ ๋ถ๋ฆฌ์ธ ๊ฐ์ ๋์ ธ์ฃผ๋ ํจ์ ๋๋ ํด๋ก์ ๋ด์. ๊ทธ๋ฆฌ๊ณ ์ด ํจ์๋ ์ ์ฒด์ ์ผ๋ก๋ -> < nil์ด๋ Double >์ ๋ฆฌํดํฉ๋๋ค. ์ต์ ๋ ๋ฐ์ธ๋ฉ์ด๋ ๋ ์ฝ์ผ๋ฆฌ์ฑ์ ์ด์ฉํ์ฌ ๋ฐ์ผ๋ฉด ๋๊ฒ ์ฃ .
4). ์ปฌ๋ ์ .map : ์ปฌ๋ ์ ์ ๊ฐ๋ค์ ์ผ๊ด์ ์ผ๋ก ํน์ ์ฐ์ฐ์ ์ ์ฉํ๊ฑฐ๋, ํ์ ๋ณํํ ๋ ( .compacetMap ์ ์ฉ )
1). ์ปฌ๋ ์ ์ ์ผ๊ด์ ์ฉ map{ $0 * 0.9 }
2). ์ปฌ๋ ์ ์ผ๊ด์ ํ์ ์ปจ๋ฒ์ ผ ex). map{ Int($0) ?? 0 } : but, have to deal with nil
3). nil์์ด ๊น๋ํ๊ฒ ์ปจ๋ฒ์ ผ .compactMap
//
let salesPrices = prices.map{
$0*0.9
}
//
let userInput = ["0", "11", "haha", "42"]
let number1 = userInput.map{
Int($0) ?? 0 // ํ์ฑ์ด ์๋ ์ ์์ผ๋ฏ๋ก, ๋ ์ฝ์ผ๋ฆฌ์ฑ
}
number1
//
userInput.compactMap{
Int( $0 )
}
// [0, 11, 42]
5). ์ปฌ๋ ์ .reduce : input์ผ๋ก starting value, closure๋ฅผ ๋ฐ๋๋ค. :
1. $1์ ์ดํฐ๋ ์ด์ ํ๋ฉฐ ๊ฐ ์์๊ฐ ๋ค์ด๊ฐ๊ณ ,
2. $0์ current state : ์ฆ ์ปฌ๋ ์ ์ ์์ฝํ ํ์ฌ ์ํ๊ฐ ๋๋ฉฐ, ์ฒซ ์ธ์๊ฐ ์ฒ์์ ๊ทธ ๊ฐ์ผ๋ก ์ด๊ธฐํ ๋ฉ๋๋ค.
3. ๊ณ์ ํด์ ํด๋ก์ ธ์ ๊ฒฐ๊ณผ๊ฐ ๋ค์ $0์ผ๋ก ๋ค์ ๋ค์ด๊ฐ๊ณ , ๋ค์ ์์์ ํด๋ก์ ์์ ์ฐ์ฐ์ด ์งํ๋ฉ๋๋ค.
let sum = prices.reduce( 0 ){
$0 + $1
}
// 0๊ณผ ํด๋ก์ ธ๋ฅผ ๋ฐ์๋ค์.
// ํน์ง์ : ์ฒซ ๋ฒ์งธ ์
๋ ฅ์ผ๋ก ๋ค์ด๊ฐ 0์ด ์ด๊ธฐ $0 : current value์ ๊ฐ์ด ๋๊ณ
// $1 : ์ปฌ๋ ์
๊ฐ ์์์ +๊ฐ ์ ์ฉ๋๊ฒ ๋ฉ๋๋ค.
" ํด๋ก์ ธ์ ์ปฌ๋ ์ ๋ฉ์๋๋ฅผ ์ด์ฉํด์, ๋ช ์๋๋ ์ค๋ก, ์ปฌ๋ ์ ์ผ๋ก ๋ถํฐ ๊ฝค ๋ณต์กํ ์๋ฏธ์๋ ๊ฐ์ ๊ณ์ฐํ ์ ์์ต๋๋ค.
let stock = [1.5: 5, 10: 2, 4.99: 20, 2.30 : 5, 8.19: 30]
let stockSum = stock.reduce(0){
$0 + $1.key * Double($1.value)
}
//384.5
// ์ปฌ๋ ์
์ธ ์ฌ์ ์ ์ ์ฉํ๋ ๋ฆฌ๋์ค๋,
// 0๊ณผ ํด๋ก์ ธ๋ฅผ ์
๋ ฅ์ผ๋ก ๋ฐ๊ณ ์๊ณ
// ๊ทธ ํด๋ก์ ธ๋, ๋๋ธ๊ฐ ํ๋์ ํํ์ ์ธํ์ผ๋ก ๋ฐ์ต๋๋ค.
// ๋ฐ์ ํํ์์ key๋ผ๋ ๊ฐ๊ณผ value๋ผ๋ ๊ฐ์ ๋๋ธ๋ก ๋ณํํ ๊ฑธ ๊ณฑํ๊ณ
// ๋ํ์ฌ "ํ์ฌ ์ํ๊ฐ"์ ๋ง๋ค๋ฉฐ
// ์ด๊ฒ์ ๋ค์ ์ดํฐ๋ ์ด์
์์ ๋ค์ $0 ๊ฐ์ผ๋ก ์ง์ด ๋ฃ์ต๋๋ค.
7). ์ฌ์ ์๋ฃ๊ตฌ์กฐ.reduce( into: , _: closure )
์๋ฅผ ๋ค์ด, ์ฌ์ ์ [String] array๋ก ์์ฝํด๋ฒ๋ฆด ๊ฒ์ด๋ผ๋ฉด, Result๋ [String]์ด ๋ ๊ฒ ์ ๋๋ค.
์ฉ๋ : 1). ์ด๋ ์ด ํฌ ๋์ ๋๋ฆฌ ํ๋ฆฌํ์ ์นด์ดํฐ, 2). ํ๋ฆฌํ์ ํฌ ์ด๋ ์ด ๋์ด๋๊ธฐ 3). ์ฌ์ ์ ๊ฐ๋ค ์์ฝ๊ฐ ๋ด์ด๋๊ธฐ
์ฐ์ต 1). ์ปฌ๋ ์ .reduce(into : ){ } < String(์ํ์ค) -> ์ฌ์ >
์ต์ํด์ง๋ ค๋ฉด, ๊ทธ๋ฅ ๋ฌดํ ์ฐ์ต. ๋ฌดํ์ผ๋ก ์ ๋๋ก ์ฐ์ตํ๋ฉด, ๋์์ ์๋์ผ๋ก ํจํด์ ๋ง๋ ๋ค๊ณ ํ๋ค์. ^^
์ด๋ฒ์ ํ ์คํธ๋ง์ด๋ผ๋ ์ํ์ค๋ฅผ ์ฌ์ ์ผ๋ก reduceํด๋ณด๊ฒ ์ต๋๋ค. into์ ์ง์ด๋ฃ์ [ : ] ๋น ์ฌ์ ์ด inout์ผ๋ก ๋ ํผ๋ฐ์ค ๋ณ์์ฒ๋ผ counts๋ก ๋ค์ด๊ฐ๊ณ , ์ดํฐ๋ ์ด์ ํ ๋๋ง๋ค, ๊ฐ ์์๊ฐ letters์ ์ง์ ๋ฉ๋๋ค. ๋ง์ง๋ง์ผ๋ก ๋ ํผ๋ฐ์ค ๋ณ์์ธ ์ฌ์ count์ ๊ฐ์ด ๋ฆฌํด๋ฉ๋๋ค.
let letters = "abracadabra"
let letterCount = letters.reduce(into: [:]) {
counts, letters in // ์ฌ์ ์ด๋์ ๋ค๋ฅด๊ฒ counts <- [ : ] ๊ฐ ๋ค์ด๊ฐ๊ณ , letters๋ ์คํธ๋ง
counts[letters, default: 0] += 1
}
// dictionary default ๊ฐ์ถ๊ฐ
var letterCount2 : [String: Int] = [ : ]
letterCount2["A", default: 1] += 1
letterCount2
์ฐ์ต 2). ์ปฌ๋ ์ .reduce(into : ){ } < ์ฌ์ -> ์ด๋ ์ด >
let farmAnimals = ["๐": 5, "๐๐ฆบ": 4, "๐
": 6]
// dict into array of unicode animals by iterating
let animalArray = farmAnimals.reduce(into: []){
(result, this: (key: String, value: Int)) in
for _ in 0 ..< this.value {
result.append(this.key)
}
}
//-> ["๐
", "๐
", "๐
", "๐
", "๐
", "๐
",
//"๐", "๐", "๐", "๐", "๐", "๐๐ฆบ", "๐๐ฆบ", "๐๐ฆบ", "๐๐ฆบ"]
* ์ฐธ๊ณ
๊ธฐํ ์ปฌ๋ ์ ๊ด๋ จ ์ ์ฉํ ๋ฉ์๋๋ค์ ๋๋ค. ex). ์ฒ์ ๋ฐ ๋ง์ง๋ง ๋จ๊ตฐ ํํ, ์ฒซ2๊ฐ ๋ง์ง๋ง 2๊ฐ๋ฅผ ์ฌ๋ผ์ด์ฑํ ๋ฆฌ์คํธ, ์ฟผ๋ฆฌํ์ฌ true๋ฅผ ๋ฆฌํดํ๋ ๊ฒ๋ค๋ง ์ ๊ฑฐํ๋ ๋ฉ์๋(mutating function)
// get the form that has dropped first and last.
// let removeFirst = prices.dropFirst()
// let removeFirstTwo = prices.dropFirst(2)
// let removeLast = prices.dropLast()
// let removeLastTwo = prices.dropLast(2)
// select first few, last few
// let firstTwo = prices.prefix(2)
// let lastTwo = prices.suffix(2)
// closure๋ฅผ ์
๋ ฅ์ผ๋ก ๋ฐ๋ ๋ฎคํ
์ดํ
ํ๋ก์์ ธ
prices.removeAll() { $0 > 15 }
// prices
//
// prices.removeAll()
// prices
----> 6). Lazy Collections
์ด๋ค ์กฐ๊ฑด์ ํด๋นํ๋, ๋ฌดํํ set์ ์ปฌ๋ ์ ์ ์ด๋ป๊ฒ ๋ค๋ฃฐ ์ ์์๊น. ( ์ด๊ฒ๋ ๊ธฐ์ตํ์ธ์ !! functional programming์ ์ด์ฉํ๋ฉด ์์ฐ์ฑ์ ์ข๋ค )
์ฐ์ ๋ฌธ์ ๋ฅผ ๋๋ฆด๊ฒ์ !! : ์์(prime number)๋ฅผ ์ฒซ 10๊ฐ๋ง ํ๋ฆฐํธํ๋ ์๊ณ ๋ฆฌ์ฆ์ ์ง๋ณด์ธ์. ํด๋์์ปฌํ๊ฒ, ๊ตณ์ด ํจ์ํ ํ๊ทธ๋๋ฐ์ผ๋ก ํ์ง ์๋๋ค๊ณ ํ๋ค๋ฉด, ๋ค์๊ณผ ๊ฐ์ด ์งค ์๋ ์์ ๊ฑฐ์์.
1). ์ด๋ค ์์ฐ์๋ฅผ ๋ฃ์ผ๋ฉด ์์์ธ์ง ์๋์ง ๋ถ๋ฆฌ์ธ์ ๋ฆฌํดํ๋ ํจ์๋ฅผ ๋ง๋ ๋ค.
2). ์์๋ค์ ๋ชจ์ ์ด๋ ์ด๋ฅผ ๋ง๋ ๋ค. ๊ทธ๋ฆฌ๊ณ , ์์์ ๊ฐ์๋ฅผ ์ ์นด์ดํธ ๋ณ์๋ฅผ ๋ง๋ ๋ค.
3). ์นด์ดํธ๊ฐ 10๋ณด๋ค ์์ ๋์, ์์ ์ด๋ ์ด์, ์ ํจ์์์ ํธ๋ฃจ๋ฅผ ๋ฆฌํดํ๋ ๊ฐ์ ์ถ๊ฐํ๋ค.
4). ์์๋ค์ 10๊ฐ ๋ชจ์ ์ด๋ ์ด์ .forEach{ print( $0 ) }๋ฅผ ์ ์ฉํ๋ค.
// 1).
func isPrime( _ number : Int ) -> Bool {
// 2,3 ์ด๋ฉด ๋ฐ๋ก true
if number == 1 {return false}
if number == 2 || number == 3 {return true}
// ์๋๋ผ๋ฉด, ๊ทธ ์ซ์์ ๋ฃจํธ๋ฅผ ์์ด ๊ฐ์ ๋ด๋ฆผํ ๊ฐ์ด ๋๋์ด ๋จ์ด์ง๋ค๋ฉด false
for i in 2...Int( Double(number).squareRoot() ){
if number % i == 0 {return false}
}
// ๊ทธ๊ฒ ์๋๋ผ๋ฉด, true
return true
}
// 2).
var primes: [Int] = []
var i = 1
while primes.count < 10 {
if isPrime(i) {
primes.append(i)
}
i += 1
}
// 3).
primes.forEach{
print($0)
}
์ด๋ ๊ฒ ํ ์๋ ์๊ฒ ์ง๋ง, ๋งค์ฐ ๋จ๊ณ๊ฐ ๋ณต์กํ๊ณ , ์ค์ํํธ์ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๊ฐ์ ์ ์ด๋ฆฌ์ง ๋ชปํ๋ค์.
์ด๋ด ๋๋,
1). ๋ฌดํ ๋ ์ธ์ง
๊ทธ๋ฆฌ๊ณ ...
2). ์ปฌ๋ ์ .lazy์ ์ธ์ ์ด์ฉํ๋ฉด ์ข์ ๊ฑฐ ๊ฐ๋ค์.
let primes2 = (1...).lazy // hey swift !! it's lazy collection
// A sequence containing the same elements as this sequence, but on which some operations, such as map and filter, are implemented lazily.
.filter{isPrime($0)} // not mutating
.prefix(10) // return an array of query
// ์ด๋๊น์ง ์ํ์ค๊ฐ ์์ฑ๋์ง๋ ์๋๋ค !!
primes2.forEach{ print($0) }
// ์ด๋ ๋ถํฐ, ์ํ์ค๊ฐ ํํฐ๋ง์ ๊ฑฐ์น๊ณ , ์ฒซ 10๊ฐ๊ฐ ์ถ๋ ค์ง๋ค.
// ๋ถ์ !!
(1...).lazy
.filter{isPrime($0)}// ์์ฐ์๋ฅผ ๊ฐ์ง๋ ๋ถ๋ถ์ ๋ ์ธ์ง ๊ฐ์ฒด
.prefix(10)
์ด๋ ๊ฒ ๋ช ์ค ์์ ๋๋ผ ์ ์์ต๋๋ค.
( 1... )
์์ฐ์๋ก 1<= ์ธ ์ปฌ๋ ์ ์ => .lazyํ ์ปฌ๋ ์ ์ ๋๋ค. ์ฌ์ฉ๋ ๋๋ง ์ด ์ปฌ๋ ์ ์ ๊ฐํด์ง๋ .filer, .prefix ๋ฑ์ ๋ฉ์๋๊ฐ ์ ์ฉ๋ฉ๋๋ค. ์ง๊ธ์ ๊ทธ์ ์์์ชฝ์ผ๋ก ๋ฌดํํ ์์ฐ์ ์ปฌ๋ ์ ์ด์ฃ .
์ด๋์
primes2.forEach{ print( $0 ) }๊ฐ ์ฐ์๋ค์. ๊ทธ๋ผ, ์ด์ ๋ฉ์๋๋ค์ ์ ์ฉํด์ผ๊ฒ ๋ค์. ์ด๊ฒ => ํํฐ๋ง์ ๊ฑฐ์น ์ด๋ ์ด => ์ฌ๊ธฐ์ 10๊ฐ๋ง ๋จ๊ธด ์ด๋ ์ด๊ฐ ๋ฆฌํด๋์ด primes๊ฐ ๋ฉ๋๋ค. ๊ทธ๋ฌํ ๊ฒ์ ๋ํด ๊ฐ ์์๋ฅผ ํ๋ฆฐํธ ํ์ต๋๋ค.
๋ด์ฉ์ ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค. ์์ด๋ก ์ ๋ฆฌํ๊ฒ ์ต๋๋ค ^^
* ๋ ์ด์ง ์ปฌ๋ ์ ์ ์๋ฐํ๊ฒ, ํ์ํ ๊ฒฝ์ฐ์๋ง ํด๋น ์์์ ๋ฉ์๋ ์คํผ๋ ์ด์ ์ ์ ์ฉํ๋ฏ๋ก, ๋งค์ฐ ๋ฌดํํ๊ฑฐ๋ ๋งค์ฐ ํฐ ์ปฌ๋ ์ ์ ๋ค๋ฃจ๋ ๋ฐ ํจ์จ์ ์ ๋๋ค.
์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
ํด๋ก์ ์์ ๋ ๋ง์ด ์ฐ์ตํด๋ณด์ธ์ ~
์ด๋ ๊ฒ ํท๊ฐ๋ฆฌ๊ฑฐ๋, ๋ํ ์ผ์ด ๋ณต์กํ ๊ฐ๋ ์ ๊ฒฝ์ฐ์๋ ์ข์ ์์ ๋ฅผ ์์์ด ํ์ด๋ณด๋ฉด์
๊ณ ๋ํ๊ณ , ๊ฒฝํํ๋ ์ ๋ฐ์ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
๋ง์ฝ ํด๋ก์ ์์ ๊ฐ ํ์ํ์๋ฉด 7616tjrgml@naver.com์ผ๋ก ๋ฉ์ผ ์ฃผ์๋ฉด ์ข์ ์์ ๋ค ๋ณด๋ด๋๋ฆฌ๊ฒ ์ต๋๋ค.