ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Swift] ๊ณ ์ฐจํ•จ์ˆ˜ (map, filter, reduce)
    Swift 2022. 1. 20. 22:30

    Swift์˜ ํ•จ์ˆ˜๋Š” First-Class Citizen (์ผ๊ธ‰๊ฐ์ฒด)์ด๋‹ค.

     

    ๋”ฐ๋ผ์„œ ํ•จ์ˆ˜๋Š”

    1. ๋ณ€์ˆ˜๋‚˜ ์ƒ์ˆ˜์— ์ €์žฅ

    2. ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ

    3. ํ•จ์ˆ˜๋‚˜ ๋ฉ”์†Œ๋“œ์—์„œ ๋ฆฌํ„ด ํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    ๊ณ ์ฐจ ํ•จ์ˆ˜ (Higher-order Function) ๋ž€ ์ธ์ž๋กœ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌ๋ฐ›๊ฑฐ๋‚˜, ํ•จ์ˆ˜๋ฅผ ๊ฒฐ๊ณผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋งํ•œ๋‹ค.

    Swift์—์„œ ์ œ๊ณตํ•˜๋Š” ๋Œ€ํ‘œ์ ์ธ ๊ณ ์ฐจํ•จ์ˆ˜๋กœ๋Š” ๋งต (map), ํ•„ํ„ฐ (filter), ๋ฆฌ๋“€์Šค (reduce)๊ฐ€ ์žˆ๋Š”๋ฐ, ์ด์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ณ ์ž ํ•œ๋‹ค.

     

    1. map (๋งต)

    Swift์—์„œ map์€ ๋ฐฐ์—ด (Array), ๋”•์…”๋„ˆ๋ฆฌ (Dictionary), ์…‹ (Set), ์˜ต์…”๋„ ๋“ฑ ์—์„œ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•œ๋ฐ, ์—ฌ๊ธฐ์„œ๋Š” ๋ฐฐ์—ด์—์„œ ์‚ฌ์šฉํ•˜๋Š” map์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ณ ์ž ํ•œ๋‹ค.

     

    map(_:) ์€ ํด๋กœ์ €๋กœ ์ „๋‹ฌ๋œ ์‹œํ€€์Šค์˜ ์š”์†Œ๋“ค์„ ๋งตํ•‘ํ•œ ํ›„์— ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด๋กœ ๋งŒ๋“ค์–ด์„œ ๋ฆฌํ„ดํ•œ๋‹ค.

    ๊ธฐ์กด ์‹œํ€€์Šค ์š”์†Œ๋“ค์˜ ๊ฐ’์€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— map์€ ๊ธฐ์กด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ˜•ํ•˜๋Š”๋ฐ ๋งŽ์ด ์“ฐ์ธ๋‹ค.

     

    for-in ๊ตฌ๋ฌธ๊ณผ ๋น„์Šทํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜์ง€๋งŒ, map ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ๋” ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    ๋ฐฐ์—ด numArr์— ์ €์žฅ๋œ ์š”์†Œ๋“ค์„ ๋ชจ๋‘ String์œผ๋กœ ๋ฐ”๊ฟ”์„œ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์— ์ €์žฅํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

    ์•„๋ž˜ ์˜ˆ์‹œ๋ฅผ ๋ณด์ž.

     

     

    for-in ๋ฌธ์„ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ์ด๋‹ค.

    numString ๋ฐฐ์—ด์„ ๋นˆ ๋ฐฐ์—ด๋กœ ์ƒ์„ฑํ•œ ํ›„์—, for-in ๋ฌธ ๋‚ด์—์„œ append ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์•ž์„œ ์ƒ์„ฑํ•œ ๋ฐฐ์—ด์— ์š”์†Œ๋“ค์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์žˆ๋‹ค.

    let numArr = [1, 2, 3, 4, 5]
    var numString: [String] = []
    
    for num in numArr {
        numString.append("\(num)")
    }
    
    print(numString) // ["1", "2", "3", "4", "5"]

     

     

     

    ์œ„ ์ฝ”๋“œ๋ฅผ map ๋ฉ”์†Œ๋“œ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

    for-in ๋ฌธ์—์„œ๋Š” ๋ณ„๋„๋กœ ๋นˆ ๋ฐฐ์—ด์„ ์ดˆ๊ธฐํ™”ํ•˜์—ฌ ์ƒ์„ฑํ•ด์ฃผ์—ˆ์ง€๋งŒ, map ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ทธ๋Ÿด ํ•„์š”๊ฐ€ ์—†๋‹ค. 

    map ๋ฉ”์†Œ๋“œ์˜ ๊ฒฐ๊ณผ ๊ฐ’์„ ๋ฐ”๋กœ ๋ฐฐ์—ด์— ์ €์žฅํ•ด์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.

    let numArr = [1, 2, 3, 4, 5]
    
    var numString = numArr.map { (number: Int) -> String in
        return "\(number)"
    }
    
    print(numString) // ["1", "2", "3", "4", "5"]

     

     

    ๋˜ํ•œ ์œ„ ์ฝ”๋“œ๋ฅผ ๋ฌธ๋ฒ• ์ตœ์ ํ™”๋ฅผ ์ด์šฉํ•˜๋ฉด ๋” ๊ฐ„๋‹จํžˆ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

    let numArr = [1, 2, 3, 4, 5]
    
    var numString = numArr.map { "\($0)" }
    print(numString) // ["1", "2", "3", "4", "5"]

     

     

    2. filter (ํ•„ํ„ฐ)

     

    Swift์—์„œ filter๋Š” ์ฃผ์–ด์ง„ ์‹œํ€€์Šค์˜ ์š”์†Œ๋ฅผ ์กฐ๊ฑด์— ๋”ฐ๋ผ ์ถ”์ถœํ•œ ํ›„์—, ๊ทธ ๊ฐ’๋“ค์„ ์ˆœ์„œ๋Œ€๋กœ ๋ฐฐ์—ด์— ํฌํ•จํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

    map๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด๋กœ ๋ฆฌํ„ดํ•ด์ค€๋‹ค.

    ํ•˜์ง€๋งŒ filter๋Š” map์ฒ˜๋Ÿผ ๊ธฐ์กด์˜ ๊ฐ’์„ ๋ฐ”๊พธ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์ฃผ์–ด์ง„ ์กฐ๊ฑด์— ๋”ฐ๋ผ ๊ฐ’์„ ์ถ”์ถœํ•˜์—ฌ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

     

    ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” isIncluded๋กœ, ์‹œํ€€์Šค์˜ ์š”์†Œ๋ฅผ ์ธ์ž๋กœ ์‚ฌ์šฉํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•  ๋ฐฐ์—ด์— ์š”์†Œ๋ฅผ ํฌํ•จํ•  ์ง€์˜ ์—ฌ๋ถ€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” Boolean ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํด๋กœ์ €์ด๋‹ค.

     

    filter ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ๋˜๋Š” ํ•จ์ˆ˜์˜ ๋ฆฌํ„ด ํƒ€์ž…์€ Bool์œผ๋กœ, ์กฐ๊ฑด์— ๋”ฐ๋ผ ํฌํ•จํ•  ๊ฐ’์ด๋ผ๋ฉด true๋ฅผ, ์•„๋‹ˆ๋ผ๋ฉด false๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. 

     

     

    ์•„๋ž˜ ์˜ˆ์‹œ๋Š” filter(_:) ๋ฉ”์†Œ๋“œ๋ฅผ ์ด๋ฆ„์˜ ๋ฌธ์ž๊ฐ€ 5์ž ๋ฏธ๋งŒ์ธ ๊ฒƒ๋“ค๋งŒ shortNames์— ์ €์žฅํ•ด์ฃผ๊ณ  ์žˆ๋‹ค.

     

    ๋ณต์žก๋„๋Š” O(n)์œผ๋กœ, ์—ฌ๊ธฐ์„œ n์€ ์‹œํ€€์Šค์˜ ๊ธธ์ด๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

     

     

     

    3. Reduce (๋ฆฌ๋“€์Šค)

    reduce๋Š” ์ฃผ์–ด์ง„ closure๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹œํ€€์Šค์˜ ์š”์†Œ๋ฅผ ์กฐํ•ฉํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

     

     

    ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” initialResult์™€ nextPartialResult๊ฐ€ ์žˆ๋‹ค.

    initialResult๋Š” ์ดˆ๊ธฐ ๋ˆ„์  ๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์ดˆ๊ธฐ๊ฐ’์„ ์ง€์ •ํ•ด์ค„ ์ˆ˜๋„ ์žˆ๋‹ค.

    closure๊ฐ€ ์ฒ˜์Œ ์‹คํ–‰๋˜๋ฉด initialResult๊ฐ€ nextPartialResult๋กœ ์ „๋‹ฌ๋œ๋‹ค.

     

    nextPartialResult๋Š” ๋ˆ„์ ๋œ ๊ฐ’๊ณผ ์‹œํ€€์Šค์˜ ์š”์†Œ๋ฅผ ์ƒˆ๋กœ์šด ๋ˆ„์  ๊ฐ’์œผ๋กœ ๊ฒฐํ•ฉํ•˜๋Š” ํด๋กœ์ €๋กœ, nextPartialResult ํด๋กœ์ €์˜ ๋‹ค์Œ ํ˜ธ์ถœ์— ์‚ฌ์šฉ๋˜๊ฑฐ๋‚˜ caller์—๊ฒŒ ๋ฐ˜ํ™˜๋˜๋Š”๋ฐ ์‚ฌ์šฉํ•œ๋‹ค.

    nextPartialResult์˜ ์ฒซ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” reduce apthemdml initialResult ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ†ตํ•ด ์ „๋‹ฌ ๋ฐ›์€ ์ดˆ๊ธฐ๊ฐ’ ๋˜๋Š” ์ด์ „ ํด๋กœ์ €์˜ ๊ฒฐ๊ณผ๊ฐ’์ด๊ณ , ๋ชจ๋“  ์ˆœํšŒ๊ฐ€ ๋๋‚˜๋ฉด reduce์˜ ์ตœ์ข… ๊ฒฐ๊ณผ๊ฐ’์ด ๋œ๋‹ค.

    nextPartialResult์˜ ๋‘๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” reduce ๋ฉ”์†Œ๋“œ๊ฐ€ ์ˆœํ™˜ํ•˜๋Š” ๋ฐฐ์—ด์˜ ์š”์†Œ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

     

    ๋ฆฌํ„ด๊ฐ’์€ ์ตœ์ข…์ ์œผ๋กœ ๋ˆ„์ ๋œ ๊ฐ’์œผ๋กœ, ๋งŒ์•ฝ ์‹œํ€€์Šค๊ฐ€ ์š”์†Œ๊ฐ€ ์—†๋‹ค๋ฉด initialResult๊ฐ€ ๊ฒฐ๊ณผ์ด๋‹ค.

     

    ์ฆ‰, ํด๋กœ์ €๊ฐ€ ๊ฐ ์š”์†Œ๋ฅผ ์ „๋‹ฌ๋ฐ›์•„ ์—ฐ์‚ฐํ•œ ํ›„์—, ์ด ๊ฐ’์„ ๋‹ค์Œ ํด๋กœ์ € ์‹คํ–‰์„ ์œ„ํ•ด ๋ฐ˜ํ™˜ํ•˜๋ฉฐ ์‹œํ€€์Šค๋ฅผ ์ˆœํ™˜ํ•˜๋Š” ํ˜•ํƒœ์ด๋‹ค.

     

    reduce(_:_:) ๋ฉ”์†Œ๋“œ๋Š” ์ „์ฒด ์‹œํ€€์Šค์˜ ์š”์†Œ ์ค‘ ๋‹จ์ผ ๊ฐ’์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค. 

    ์˜ˆ๋ฅผ ๋“ค๋ฉด, ์ˆซ์ž๋กœ ์ด๋ฃจ์–ด์ง„ ๋ฐฐ์—ด์—์„œ ๊ทธ๋“ค์˜ ํ•ฉ ๋˜๋Š” ๊ณฑ์„ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ด ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

    nextPartialResult ํด๋กœ์ €๋Š” initialResult๋กœ ์ดˆ๊ธฐํ™”๋œ ๋ˆ„์  ๊ฐ’๊ณผ ์‹œํ€€์Šค์˜ ๊ฐ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ˆœ์ฐจ์ ์œผ๋กœ ํ˜ธ์ถœ๋œ๋‹ค.

     

    ์•„๋ž˜ ์˜ˆ์ œ๋Š” ์ˆซ์ž๋กœ ์ด๋ฃจ์–ด์ง„ ๋ฐฐ์—ด์—์„œ ๋ฐฐ์—ด ์š”์†Œ๋“ค์˜ ํ•ฉ์„ ์ฐพ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

    numbers.reduce(_:_:)๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ๋‹จ๊ณ„๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

    1. nextPartialResult ํด๋กœ์ €๋Š” initialResult๊ฐ€ 0์ธ ์ƒํƒœ๋กœ ํ˜ธ์ถœ๋œ๋‹ค. numbers์˜ ์ฒซ๋ฒˆ์งธ ์š”์†Œ๋Š” 1์ด๊ธฐ ๋•Œ๋ฌธ์— ํ•ฉ๊ณ„ 1์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

    2. ํด๋กœ์ €๊ฐ€ ์ด์ „ ํ˜ธ์ถœ์˜ ๋ฆฌํ„ด ๊ฐ’๊ณผ ์‹œํ€€์Šค์˜ ๊ฐ ์š”์†Œ์™€ ํ•จ๊ป˜ ๋‹ค์‹œ ๋ฐ˜๋ณต์ ์œผ๋กœ ํ˜ธ์ถœ๋œ๋‹ค.

    3. ์‹œํ€€์Šค ๋๊นŒ์ง€ ๋ชจ๋‘ ํ˜ธ์ถœํ–ˆ๋‹ค๋ฉด, ๋งˆ์ง€๋ง‰ ํด๋กœ์ €์—์„œ ๋ฐ˜ํ™˜๋œ ๊ฐ’์ด caller์—๊ฒŒ ๋ฐ˜ํ™˜๋œ๋‹ค.

    ๋งŒ์•ฝ ์‹œํ€€์Šค๊ฐ€ ์–ด๋–ค ์š”์†Œ๋„ ๊ฐ–์ง€ ์•Š๋Š”๋‹ค๋ฉด, nextPartialResult๋Š” ์ ˆ๋Œ€ ์‹คํ–‰๋˜์ง€ ์•Š๊ณ , initialResult๊ฐ€ reduce(_:_:)๊ฐ€ ํ˜ธ์ถœ ๊ฒฐ๊ณผ๊ฐ€ ๋œ๋‹ค.

     

    ๋ณต์žก๋„๋Š” O(n)์œผ๋กœ, ์—ฌ๊ธฐ์„œ n์€ ์‹œํ€€์Šค์˜ ๊ธธ์ด๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

     

     

    reduce ์˜ˆ์ œ1

    ๋ฐฐ์—ด nums์— ์žˆ๋Š” ์ˆซ์ž๋“ค์˜ ๊ณฑ์„ ๋ชจ๋‘ ๊ตฌํ•˜๋Š” ๋ฐฉ๋ฒ•

    import UIKit
    
    var nums = [1, 2, 3, 4, 5]
    
    var a1 = nums.reduce(1, { (num1: Int, num2: Int) -> Int in
        return num1 * num2
    })
    
    // ํŒŒ๋ผ๋ฏธํ„ฐ ํ˜•์‹, ๋ฆฌํ„ด ํ˜•์‹ ์ƒ๋žต
    var a2 = nums.reduce(1, { (num1, num2) in
        return num1 * num2
    })
    
    // ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„ ์ƒ๋žต, in ํ‚ค์›Œ๋“œ ์ƒ๋žต, ํด๋กœ์ € ๋ฐ”๋”” ๋‚ด์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ shorthand Argument Name์œผ๋กœ ๋ณ€๊ฒฝ
    var a3 = nums.reduce(1, {
        return $0 * $1
    })
    
    // ๋‹จ์ผ return๋ฌธ์ด๋ฏ€๋กœ return ํ‚ค์›Œ๋“œ ์ƒ๋žต
    var a4 = nums.reduce(1, {
        $0 * $1
    })
    
    // ๋งˆ์ง€๋ง‰ ํŒŒ๋ผ๋ฏธํ„ฐ์ด๋ฏ€๋กœ trailing closure๋กœ ๋ณ€๊ฒฝ
    var a5 = nums.reduce(1) { $0 * $1 }
    
    // ์—ฐ์‚ฐ์ž๋Š” ์ค‘์œ„ ์—ฐ์‚ฐ์ž์ด๋ฏ€๋กœ ์™ผ์ชฝ ๊ฐ’์ด $0, ์˜ค๋ฅธ์ชฝ ๊ฐ’์ด $1์ž„์„ ์ถ”๋ก ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€ํ˜• ๊ฐ€๋Šฅ
    var a6 = nums.reduce(1, *)
    
    print("=======")
    print(a1)
    print(a2)
    print(a3)
    print(a4)
    print(a5)
    print(a6)
    print("=======")

     

     

    reduce ์˜ˆ์ œ2

    ๋ฐฐ์—ด์— ์žˆ๋Š”์š”์†Œ๋ฅผ ๋ชจ๋‘ ํ•ฉ์ณ์„œ String์œผ๋กœ ์ถœ๋ ฅํ•˜๋Š” ๋ฐฉ๋ฒ•.

    ์ด ๋•Œ result์˜ ํƒ€์ž…์€ String์ด๋‹ค.

    ์ฝ”๋“œ

     

    ์ถœ๋ ฅ ๊ฒฐ๊ณผ

    let arr = ["A", "B", "C", "D", "E", "F", "G", "H"]
    
    let result = arr.reduce("์‹œ์ž‘!\n", {
        print($0)
        return $0 + "\($1)"
    })
    
    print(result)

     

    ๋Œ“๊ธ€

Designed by Tistory.