새소식

iOS/Swift

[Swift] 맵, 필터, 리듀스

  • -
참조 : Swift 스위프트 프로그래밍 3판 Swift 5, 저자 야곰 (한빛미디어) , The Swift Programming Language Swift 5.6 Edition (iBooks)(https://books.apple.com/kr/book/the-swift-programming-language-swift-5-6/id881256329)

 

 

맵(Map)


- 자신을 호출할 때 매개변수로 전달된 함수를 실행하여 그 결과를 다시 반환해주는 함수

- Array, Dictionary, Set, Optional에서 사용 가능 → Swift의 Sequence, Collection 프로토콜을 따르는 타입과 옵셔널에서 사용 가능

- 컨테이너가 담고 있던 각각의 값을 매개변수를 통해 받은 함수에 적용한 후 다시 컨테이너에 포장하여 반환

- 기존 컨테이너의 값은 변경되지 않고 새로운 컨테이너가 생성되어 반환

- 맵은 기존 데이터를 변형하는데 많이 사용

 

- map 사용하는 것은 for-in 구문과 유사, 다만 코드의 재사용/컴파일러 최적화 측면에서 보면 성능에서 차이가 있음

- 다중 스레드 환경일 때, 예측치 못한 결과가 발생하는 부작용을 방지할 수 있음

 

//for-in문 vs map 매서드

let numbers:[Int] = [0, 1, 2, 3, 4]

var doubledNumbers: [Int] = [Int]()
var strings: [String] = [String]()

//for-in
for number in numbers {
	doubledNumbers.append(number*2)
	strings.append("\(numbers)")
}

print(doubledNumbers) // [0, 2, 4, 6, 8]
print(strings) // ["0", "1", "2", "3", "4"]

//map매서드
doubledNumbers = numbers.map({ (number: Int) -> Int in
	return number * 2
})
strings = numbers.map({ (number: Int) -> Int in
	return "\(number)"
})

print(doubledNumbers) // [0, 2, 4, 6, 8]
print(strings) //["0", "1", "2", "3", "4"]

 

- 클로저를 사용하여 간략화할 수 있음

// 클로저 사용
let numbers: [Int]

// 기본 클로저 표현식 사용
var doubledNumbers = numbers.map({ (number: Int) -> Int in
	return number * 2
})

// 매개변수 및 반환 타입 생략
doubledNumbers = numbers.map{( return $0 * 2 )}
print(doubledNumbers) // [0, 2, 4, 6, 8]

// 반환 키워드 생략
doubledNumbers = numbers.map({ $0 * 2 })
print(doubledNumbers) // [0, 2, 4, 6, 8]

// 후행 클로저 사용
doubledNumbers = numbers.map { $0 * 2 }
print(doubledNumbers) // [0, 2, 4, 6, 8]

 

 

 

 

 

필터(Filter)


- 맵과 마찬가지로 새로운 컨테이너에 값을 담아 반환

- 다만 맵과 다르게 특정 조건에 맞게 걸러내는 역할을 할 수 있음 → filter의 반환 타입은 Bool

- 해당 콘텐츠의 값이 새로운 컨테이너에 포함될 항목이면 true, 아니면 false를 반환

 

let numbers: [Int] = [0, 1, 2, 3, 4, 5]

let evenNumbers:[Int] = numbers.filter { (number:Int) -> Bool in
	return number % 2 == 0
}
print(evenNumbers) // [0, 2, 4]

let oddNumbers: [Int] = numbers.filter { $0 % 2 == 1 }
print(oddNumbers) // [1, 3, 5]

 

 

- 맵과 필터 매서드를 체인처럼 연결해서 사용 가능

let oddNumbers: [Int] = numbers.map{ $0 + 3 }.filter{ $0 + 2 == 1}
print(oddNumbers) // [3, 5, 7]

 

 

 

리듀스(Reduce)


- 컨테이너 내부의 콘텐츠를 하나로 합하는 기능을 실행하는 고차 함수

- 리듀스의 두 가지 형태

  1. 클로저가 각 요소를 전달받아 연산한 후 값을 다음 클로저 실행을 위해 반환하며 컨테이너를 순환하는 형태
  2. 컨테이너를 순환하며 클로저가 실행되지만 클로저가 따로 결괏값을 반환하지 않는 형태
let numbers: [Int] = [1, 2, 3]

// 첫번째 형태인 reduce(_:_:) 메서드 사용
// 초깃값이 0이고 정수 배열의 모든 값을 더함
var sum: Int = numbers.reduce(0, { (result: Int, next: Int) -> Int in
	print("\(result) + \(next)")
    // 0 + 1
    // 1 + 2
    // 2 + 3
    return result + next
})

print(sum) // 6

// 초깃값이 0이고 정수 배열의 모든 값을 뺌
let subtract: Int = numbers.reduce(0, { (result: Int, next: Int) -> Int in
	print("\(result) - \(next)")
    // 0 - 1
    // -1 - 2
    // -3 - 3
    return result - next
})

print(subtract) // -6

// 초깃값이 3이고 정수 배열의 모든 값을 더함
let sumFromThree: Int = numbers.reduce(3){
	print("\($0) + \($1)")
	// 3 + 1
    // 4 + 2
    // 6 + 3
	return $0 + $1
}

print(sumFromThree) // 9

// 문자열 배열을 reduce(_:_:) 매서드를 이용하여 연결
let names: [String] = ["kim", "kwak", "han", "jay"]

let reducedNames: String = names.reduce("son's friends : "){
	return $0 + ", " + $1
}

print(reducedNames) // "son's friends : , kim, kwak, han, jay"

//두번째 형태 reduce(into:_:_)
//초깃값이 0이고 정수 모든 배열을 더함
sum = numbers.reduce(into: 0, { (result: inout Int, next: Int) in
	print("\(result) + \(next)")
    // 0 + 1
    // 1 + 2
    // 3 + 3
    result += next
})

print (sum) 6
728x90

'iOS > Swift' 카테고리의 다른 글

[Swift] 함수  (0) 2022.09.14
[Swift] 연산자  (0) 2022.09.14
[Swift] regular expression  (0) 2022.09.07
[Swift] 배열  (0) 2022.09.07
[Swift] 조건문, 반복문  (0) 2022.09.04
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.