์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๊ณ ์ฐจํ•จ์ˆ˜๋“ค์— ๋Œ€ํ•ด์„œ ์ดํ•ดํ•ด๋ณด์ž.map, flatMap๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์กด์žฌํ•˜๋Š”๋ฐ, ๊ฐ๊ฐ์˜ ํ™œ์šฉ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.

Documentation ํ™•์ธ

forEach

  • forEach

  • for-in loop์™€ ์œ ์‚ฌํ•œ ๋™์ž‘

  • for each in [1, 2, 3] {
        if each == 2 {
            break // for-in๋ฌธ์˜ ๊ฒฝ์šฐ break ๊ฐ€๋Šฅ
        }
        print(each)
    }
     
    // forEach์˜ ๊ฒฝ์šฐ break ๋ถˆ๊ฐ€๋Šฅ
    [1, 2, 3].forEach { (each: int) in
        print(each)
    }
  • ์–ด๋–ป๊ฒŒ์— ์ง‘์ค‘๋˜์–ด ์žˆ๋Š” for in๋ฌธ์€, ํŠน์ • ์ปฌ๋ ‰์…˜์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ๋•Œ ๋กœ์ง์„ ๋ณ€๊ฒฝํ•ด์ฃผ์–ด์•ผ ํ•จ

  • ํ•˜์ง€๋งŒ forEach๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋™์ž‘์„ ๊ต์ฒดํ•˜์—ฌ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์—์„œ ๋ณด๋‹ค ๊ฐ„๊ฒฐํ•จ

filter

  • filter
  • ํŠน์ • ์กฐ๊ฑด์„ ์ถฉ์กฑํ•˜๋Š” element๋“ค์„ filteringํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ

reduce

  • reduce
  • Element๋“ค์„ ์ด์šฉํ•˜์—ฌ ์ตœ์ข… ๊ฒฐ๊ณผ ํ•˜๋‚˜๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ
  • Summation์—์„œ ์ž์ฃผ ์‚ฌ์šฉ

map

  • map: Sequence
  • map: Optional
  • Element๋ฅผ Transform์„ ์ด์šฉํ•˜์—ฌ ๋‹ค๋ฅธ Type์˜ Element๋กœ ๋ณ€ํ™˜
  • Optional๋„ Map Function์„ ๊ฐ€์ง
  • ๊ฐ’์ด ์กด์žฌํ•  ๋•Œ ์‹คํ–‰
    • ์˜ˆ์‹œ

    • Optional์˜ ๊ฐ’์ด ์žˆ๋Š” ๊ฒฝ์šฐ map์•ˆ์˜ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰

    •   let tempName: String? = "wansik"
        let checker: (String) -> String? = { name in
            if name == "wansik" {
                return "nice"
            }
            return nil
        }
       
        let result = tempName.map(checker)
        print(result) // if "wansik": Optional(Optional("nice")), else: Optional(nil)
    • tempName์ด Optional์ธ ๊ฒฝ์šฐ map ๊ตฌ๋ฌธ์ด ์‹คํ–‰๋˜์ง€ ์•Š๊ณ  ๊ฒฐ๊ณผ๊ฐ€ nil์ด๋‹ค.

    • ํ•˜์ง€๋งŒ Optional์ด ์•„๋‹ˆ๊ณ  wansik์ด ๋“ค์–ด๊ฐ”์„ ๋•Œ, Optional Map์˜ ๊ฒฝ์šฐ ์›๋ž˜ context์— wrappingํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ Optional์ด ์ค‘์ฒฉ๋œ๋‹ค.

    • ๋งŒ์•ฝ wansik์ด ์•„๋‹Œ ๋‹ค๋ฅธ ๊ฐ’์ด ๋“ค์–ด๊ฐ”์„ ๋•Œ ์—ญ์‹œ Optional(nil)๋กœ ๋ฐ˜ํ™˜๋œ๋‹ค.

    • ์ด๋Ÿฌํ•œ ๋ถ€๋ถ„์ด ์ƒ๋‹นํžˆ ๋ถˆํŽธํ•˜๋‹ค. ์ด๋Ÿฐ ๋ถˆํŽธํ•จ์€ flatmap์„ ํ™œ์šฉํ•˜์—ฌ ํ•ด๊ฒฐ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ์šฉ์–ด
  • Context
    • Collection, Optional๊ณผ ๊ฐ™์ด ์–ด๋–ค Value๋ฅผ ํฌํ•จํ•˜๋Š” ์ž๋ฃŒํ˜•
  • Value
    • Context์•ˆ์— ๋“ค์–ด์žˆ๋Š” ์‹ค์ œ ๊ฐ’
  • Transform
    • ์–ด๋–ค Value๋ฅผ ๋‹ค๋ฅธ Value๋กœ ์‚ฌ์ƒํ•˜๋Š” function
  • Functor (ํ•จ์ž)
    • Value๋ฅผ ๊ฐ€์ง€๋Š” Context๊ฐ€ Map function์„ ์ด์šฉํ•œ Transform์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ

flatMap

  • flatMap: Sequence

  • flatMap: Optional

  • flatMap

  • Map + Flatten

  • Transform์˜ ๊ฒฐ๊ณผ๊ฐ€ Context์™€ ๋™์ผํ•œ Type์˜ Context๋ผ๋ฉด, ๊ฒฐ๊ณผ๋Š” Context๊ฐ€ ์ค‘์ฒฉํ•ด์„œ ์กด์žฌํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด๋ฅผ ํ•˜๋‚˜๋กœ ๋ณ€ํ™˜์‹œํ‚จ ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“ฆ

    • Transform์˜ ๊ฒฐ๊ณผ๊ฐ€ Optional Int์ธ ๊ฒฝ์šฐ, Context ์—ญ์‹œ Optional Int๋ผ๋ฉด, ๊ฒฐ๊ณผ๋Š” Optional์ด ์ค‘์ฒฉ๋œ ์ƒํƒœ๊ฐ€ ๋จ
    • ์ด ๋–„, Flatmap์„ ์‚ฌ์šฉํ•˜๋ฉด flatten๋œ ๊ฒฐ๊ณผ๋ฌผ๋กœ ๋งŒ๋“ค์–ด์คŒ
      let result = value.map { (num: Int) -> Int? in
          if num % 3 == 0 {
              return nil
          }
          return 3
      }
      // Optional(Optional(3))
       
      let result = value.flatMap { (num: Int) -> Int? in
          if num % 3 == 0 {
              return nil
          }
          return 3
      }
      // Optional(3)
  • ์ด์ค‘ Collection (์ด์ฐจ์› ๋ฐฐ์—ด)์˜ ๊ฒฝ์šฐ 1์ฐจ์›์œผ๋กœ ๋ณ€ํ™˜ํ•ด์คŒ

    let numbers = [[1, 2, 3, [4, 5, 6], [7, 8, 9]]
    let result = numbers.flatMap { $0 }
    // [1, 2, 3, 4, 5, 6, 7, 8, 9]
  • Dictionary์˜ ๊ฒฝ์šฐ ๊ฐ Element๋Š” tuple๋กœ ๋ฐ›์Œ

    • ๊ฒฐ๊ณผ๋Š” [Sequence.Element]
  • Optional์ธ ๊ฒฝ์šฐ, ๊ทธ๋ฆฌ๊ณ  ๋™์ž‘์˜ ์‹คํŒจ์ผ ๊ฒฝ์šฐ nil์„ ๋ฐ˜ํ™˜๋ฐ›๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉ

    • Map์—์„œ ์˜ˆ์‹œ๋ฅผ ๋‹ค์‹œ ๊ฐ€์ ธ์™€์„œ ์ดํ•ดํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ๋‹ค.
    let tempName: String? = "wan"
    let checker: (String) -> String? = { name in
        if name == "wansik" {
            return "nice"
        }
        return nil
    }
     
    let result = tempName.flatMap(checker)
    print(result) // if "wansik": Optional("nice"), else: nil
    • map๊ณผ ์ฐจ์ด์ ์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.
    • Optional Value์ธ ๊ฒฝ์šฐ nil์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. (map๊ณผ ๋™์ผํ•˜๊ฒŒ ๋™์ž‘)
    • Optional Value๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ, map๊ณผ ๋น„์Šทํ•˜๊ฒŒ ๋™์ž‘ํ•˜๋˜, transform์˜ ๊ฒฐ๊ณผ๋ฅผ ํ•œ๋ฒˆ๋” wrappingํ•˜์ง€ ์•Š๊ณ  flatenํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • ๋„คํŠธ์›Œํฌ ์ฒ˜๋ฆฌ์—์„œ json์„ ๋ฐ›๊ณ , ์ด๋ฅผ ํŒŒ์‹ฑํ•˜๋Š” ๊ฒฝ์šฐ์— ์ž์ฃผ ์‚ฌ์šฉํ•œ๋‹ค.

    let json: [String: String]? = someFunction() // ๋„คํŠธ์›Œํฌ ์ฒ˜๋ฆฌ๋ฅผ ํ†ตํ•ด ๋ฐ›์•„์˜จ json, Optional
    let model = json.flatMap(Model.init) // json์˜ ๊ฐ’์ด ์—†์–ด๋„ nil, Model ์ดˆ๊ธฐํ™”์— ์‹คํŒจํ•ด๋„ nil
    // Model init์€ failable initializer๋ผ๊ณ  ๊ฐ€์ •
    • ๋งŒ์•ฝ, map์„ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด json์˜ ๊ฐ’ ์—ฌ๋ถ€๋Š” ํ™•์ธํ•˜์—ฌ nil๋กœ ๋ฐ˜ํ™˜๋ฐ›์„ ์ˆ˜ ์žˆ์ง€๋งŒ
    • Model ์ดˆ๊ธฐํ™” ์ฝ”๋“œ์˜ ๊ฒฐ๊ณผ๋Š” Optional๋กœ wrapping๋˜์–ด ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆํŽธ
  • ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Œ

    func defaultDescription(with str: String?) -> String {
    guard let string = str,
            let integer = Int(string),
            integer <= 100 else {
                return "invalid value"
            }
    return "number is \(integer)"
    }
     
    func functionalDescription(with str: String?) -> String {
        let result = str.flatMap({ Int($0) })
                        .flatMap({ $0 <= 100 ? $0 : nil})
                        .map({ "number is \($0)"})
        return result ?? "invalid value"
    }
     
    print(defaultDescription(with: "300"))
    print(functionalDescription(with: "300"))
  • Monad

    • ์ด์ฒ˜๋Ÿผ value๋ฅผ ๊ฐ€์ง€๋Š” Context๊ฐ€ flatMap function์„ ์ด์šฉํ•œ transform์„ ์ง€์›ํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๋งํ•จ
    • Optional, Collection

compactMap

  • compactMap

  • Collection ์•ˆ์˜ nil์„ ์ œ๊ฑฐ

    let numbers: [Int?] = [1, 2, 3, nil, 4, 5, 6, nil, 7, 8, 9]
    let result: [Int] = numbers.compactMap { $0 }
     
    print(result) // 1, 2, 3, 4, 5, 6, 7, 8, 9
    • ๊ฒฐ๊ณผ๊ฐ€ [Int]๋ผ๋Š” ๊ฒƒ์— ์ฃผ์˜
  • Swift 4.1์—์„œ ๋ถ„๋ฆฌ๋œ ์ด์œ 

    • ๊ธฐ์กด์—๋Š” array ์•ˆ์— nil ์—ญ์‹œ flatten ํ•ด์คฌ์Œ
    • ํ•˜์ง€๋งŒ ํ—ท๊ฐˆ๋ฆฌ๊ฒŒ ์‚ฌ์šฉํ•˜๋‹ค๋ณด๋‹ˆ ๊ตฌ๋ถ„ํ•  ํ•„์š”์„ฑ์„ ๋Š๋‚Œ
    • flatMap
      • 2์ฐจ์› 1์ฐจ์›์œผ๋กœ
      • ๋‚ด๋ถ€ ํ•จ์ˆ˜ ์‹คํŒจ ์—ฌ๋ถ€๋ฅผ wrappingํ•˜๊ณ  ์‹ถ์ง€ ์•Š์„ ๋•Œ
    • compactMap
      • 1์ฐจ์› Collection์˜ nil์„ ์ œ์™ธํ•˜๊ณ  ์‹ถ์„ ๋•Œ

compactMapValue

  • compactMapValue
  • Swift 5์— ๋“ค์–ด๊ฐ
  • [T: S?] ์ƒํ™ฉ์˜ dictionary์—์„œ value๊ฐ€ nil์ธ element๋ฅผ ์ œ๊ฑฐํ•  ๋•Œ ์‚ฌ์šฉ
  • ๊ฒฐ๊ณผ๋ฌผ์€ [T: S]