일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- GoCD
- postgres
- kitura
- perfect
- sshpass
- nohup
- 28015
- nGrinder
- Jupyter
- postgresql
- insert
- appium
- Materials
- PYTHON
- create table
- nmap
- Jupyter Notebook
- appium server
- ftp
- port forwarding
- STF
- STF_PortForwarding
- rethinkdb
- mysql
- ssh
- openpyxl
- 실행권한
- SWIFT
- ubuntu
- centos
- Today
- Total
don't stop believing
Map 사용하기 본문
Map은 자신을 호출할 때 매개별수로 전달된 함수를 실행하여 그 결과를 다시 반환해주는 함수입니다. Swift에서 Map은 Arry, Dictionary, Set, Optional 등에서 사용할 수 있습니다. 조금 더 정확히 말하자면 Swift의 Sequence, Collection 프로토콜을 따르는 타입과 옵셔널은 모두 맵을 사용할 수 있습니다.
Map을 사용하면 컨테이너가 담고 있던 각각의 값을 매개변수를 통해 받은 함수에 적용한 후 다시 컨테이너에 포장하여 반환합니다. 기존 컨테이너의 값은 변경되지 않고 새로운 컨테이너가 생성되어 반환합니다. 그래서 Map은 기존 데이터를 변형하는 데 많이 사용 합니다.
map 메써드의 사용법은 for-in 구문과 별반 차이가 없습니다. 다만 코드의 재사용 측면이나 컴파일러 최적화 측면에서 본다면 성능 차이가 있습니다. 또, 다중 스레드 환경일때 대상 컨테이너의 값이 스레드에서 변경되는 시점에 다른 스레드에서도 동시에 값이 변경되려고 할 때 예측치 못한 결과가 발생하는 부작용을 방지할 수도 있습니다.
아래는 for-in을 이용해 Arry로 있는 숫자에 2를 곱하는 코드입니다.
12345678910111213let numbers: [Int] = [1, 2, 3, 4, 5, 6]var doubledNumber: [Int] = [Int]()var strings: [String] = [String]()// for 구문 사용for number in numbers {doubledNumber.append(number * 2)strings.append("\(number)")}print(doubledNumber) // [2, 4, 6, 8, 10, 12]print(strings) // ["1", "2", "3", "4", "5", "6"]
위 코드를 map을 이용해 변경해 봅시다.
12345678910111213141516let numbers: [Int] = [1, 2, 3, 4, 5, 6]var doubledNumber: [Int] = [Int]()var strings: [String] = [String]()// map 메서드 사용doubledNumber = numbers.map({ (number: Int) -> Int inreturn number * 2})strings = numbers.map({ (number: Int) -> String inreturn "\(number)"})print(doubledNumber) // [2, 4, 6, 8, 10, 12]print(strings) // ["1", "2", "3", "4", "5", "6"]
위 map을 사용한 코드를 closure 표현식을 사용해 더 간략화해볼 수 있습니다.
1234567891011121314151617181920let numbers: [Int] = [1, 2, 3, 4, 5, 6]var doubledNumber: [Int] = [Int]()var strings: [String] = [String]()// 기본 closure 표현식 사용doubledNumber = numbers.map({ (number: Int) -> Int inreturn number * 2})// 매개변수 및 반환 타입 생략doubledNumber = numbers.map({ return $0 * 2 })// 반환 키워드 생략doubledNumber = numbers.map({ $0 * 2 })// 후행 closure 사용doubledNumber = numbers.map { $0 * 2}print(doubledNumber) // [2, 4, 6, 8, 10, 12]
Closure 표현을 간략화하니 조금씩 코드가 더 간결해졌습니다. 그런데 처음에 언급했던 코드의 재사용 측면에 대해 생각해볼 필요가 있습니다. 같은 기능을 여러 번 사용할 것이라면 하나의 Closure를 여러 메서드에서 사용하는 편이 좋을 것 같습니다.
아래와 같이 재사용 가능한 코드로 재구성할 수 있습니다.
123456789let evenNumbers: [Int] = [0, 2, 4, 6, 8]let oddNumbers : [Int] = [0, 1, 3, 5, 7]let multiplyTwo: (Int) -> Int = { $0 * 2 }let doubledEvenNumbers = evenNumbers.map(multiplyTwo)print(doubledEvenNumbers) // [0, 4, 8, 12, 16]let doubledOddNumbers = oddNumbers.map(multiplyTwo)print(doubledOddNumbers) // [0, 2, 6, 10, 14]
map 메써드는 배열에서만 사용할 수 있는 것은 아닙니다. 여러 컨테이너 타입에 모두 적용이 가능합니다.
1234567891011121314151617181920212223242526272829let alphabetDictionary: [String: String] = ["a": "A", "b": "B"]// closure 기본 표현식var keys: [String] = alphabetDictionary.map { (tuple: (String, String)) -> String inreturn tuple.0}// 딕셔너리 타입의 간략화keys = alphabetDictionary.map { $0.0 }print(keys)// 딕셔너리 타입let values: [String] = alphabetDictionary.map { $0.1 }print(values)// Set 타입var numberSet: Set = [1, 2, 3, 4, 5]let resultSet = numberSet.map { $0 * 2 }print(resultSet)// 옵셔널 타입let optionalInt: Int? = 3let resultInt: Int? = optionalInt.map { $0 * 2 }print(optionalInt)// range 타입let range: CountableClosedRange = (0...3)let resultRange: [Int] = range.map { $0 * 2 }print(resultRange)
map 메서드를 사용해 여러 자료를 손쉽게 연산할 수 있습니다.
'Swift > Basic' 카테고리의 다른 글
Reduce 사용하기 (0) | 2018.02.19 |
---|---|
Filter 사용하기 (0) | 2018.02.19 |
탈출 클로저 @escaping (0) | 2018.01.31 |
defer (후처리) (0) | 2018.01.24 |
Swift Access Control (0) | 2018.01.19 |