티스토리 뷰
1. CaseIterable의 allCases를 초간단하게 보고
2. 거기서 reduce와 map의 조합을 볼 생각
Swift의 열거형은 enum 이라는 키워드로 선언할 수 있다.
그리고 이 enum은 CaseIterable 프로토콜을 채택할 수 있는데, 그러면 allCases라는 이름의 타입 프로퍼티를 통해 enum의 모든 케이스의 컬렉션을 생성해준다.
enum School: CaseIterable {
case elementary
case middle
case high
}
let allCases: [School] = School.allCases
print(allCases)
// [School.elementary, School.middle, School.high]
(이런식으로)
그리고 이 글 쓰게 한 예시는..
enum PastaTaste: CaseIterable {
case cream, tomato
}
enum PizzaDough: CaseIterable {
case cheeseCrust, thin, original
}
enum PizzaTopping: CaseIterable {
case pepperoni, cheese, bacon
}
enum MainDish: CaseIterable {
case pasta(taste: PastaTaste)
case pizza(dough: PizzaDough, topping: PizzaTopping)
case chicken(withSauce: Bool)
case rice
static var allCases: [MainDish] {
return PastaTaste.allCases.map(MainDish.pasta)
+ PizzaDough.allCases.reduce([]) { (result, dough) -> [MainDish] in
result + PizzaTopping.allCases.map { (topping) -> MainDish in
MainDish.pizza(dough: dough, topping: topping)};
}
+ [true, false].map(MainDish.chicken)
+ [MainDish.rice]
}
}
print(MainDish.allCases.count)
print(MainDish.allCases)
이건데
14
[MainDish.pasta(taste: PastaTaste.cream), MainDish.pasta(taste: PastaTaste.tomato),
MainDish.pizza(dough: PizzaDough.cheeseCrust, topping: PizzaTopping.pepperoni),
MainDish.pizza(dough: PizzaDough.cheeseCrust, topping: PizzaTopping.cheese),
MainDish.pizza(dough: PizzaDough.cheeseCrust, topping: PizzaTopping.bacon),
MainDish.pizza(dough: PizzaDough.thin, topping: PizzaTopping.pepperoni),
MainDish.pizza(dough: PizzaDough.thin, topping: PizzaTopping.cheese),
MainDish.pizza(dough: PizzaDough.thin, topping: PizzaTopping.bacon),
MainDish.pizza(dough: PizzaDough.original, topping: PizzaTopping.pepperoni),
MainDish.pizza(dough: PizzaDough.original, topping: PizzaTopping.cheese),
MainDish.pizza(dough: PizzaDough.original, topping: PizzaTopping.bacon),
MainDish.chicken(withSauce: true), MainDish.chicken(withSauce: false),
MainDish.rice]
출력값은 이렇다.
여기서 이해가 잘 안 갔던건
PizzaDough.allCases.reduce([]) { (result, dough) -> [MainDish] in
result + PizzaTopping.allCases.map { (topping) -> MainDish in
MainDish.pizza(dough: dough, topping: topping)};
}
이 부분 😱
allCases, reduce, map 따로는 이해가는데 합치니까 이해 안 감.
그래서 뜯어보자..
reduce, map 은 어느정도 이해했다는 가정하에)
우선 안부터 봐야 하는데
PizzaTopping.allCases.map { (topping) -> MainDish in
MainDish.pizza(dough: dough, topping: topping)};
이거.
-> 출력값 얘기할 땐 편의상 한국어로 작성
위 코드의 map 되는 과정을 하나씩 밟아보자.
피자토핑.allCases = [피자토핑.페퍼로니, 피자토핑.치즈, 피자토핑.베이컨]
이렇게 나올텐데 이 배열의 "원소" 하나를 topping이라고 이름 짓고 이걸 input
그리고 그 input이 map을 거쳐 나오는 output/결과값이 MainDish 타입으로 나옴.
topping -> map -> MainDish
어떻게 map 할건데 ? -> MainDish.pizza(dough: dough, topping: topping) 모양으로 ㅇㅇ
topping은 순서대로 페퍼로니, 치즈, 베이컨이 될 걸 아는데
dough는 어디서 오는거야 하고 보니까 바깥에
PizzaDough.allCases.reduce([]) { (result, dough) -> [MainDish] in
여기서 오고 있음 😭
그래서 map을 보다말고 reduce를 보러 가게 됨 🏃🏻♀️
한 단계씩 보자
PizzaDough.allCases = [피자도우.치즈크러스트, 피자도우.씬, 피자도우.오리지널]
reduce는 (result, dough)가 들어가서 [MainDish] 배열로 나오는 함수임.
근데 잘 보면
reduce([]) 로 초기값을 []로 주고 있다. => result의 첫 값이 []로 빈 배열임.
그러면
첫 단계에서
result = [] dough = 피자도우.치즈크러스트 가 됨.
난 아직 첫 단계에 있다는 걸 잊지말고
...
reduce의 첫 단계의 dough = 피자도우.치즈크러스트를 들고 다시 map으로 들어가서
(topping) -> MainDish in MainDish.pizza(dough: dough, topping: topping)
여기 적용한다
그러면 map의 결과값으로
[MainDish.pizza(dough: 피자도우.치즈크러스트, topping: 피자토핑.페퍼로니),
MainDish.pizza(dough: 피자도우.치즈크러스트, topping: 피자토핑.치즈),
MainDish.pizza(dough: 피자도우.치즈크러스트, topping: 피자토핑.베이컨)] 가 나오겠지 ??
cf. 배열 map 돌리면 그 안에서는 Int -> Int 라고 표현해도 당연히(?) 전체는 배열이 됨.
Int -> Int 는 안에 원소의 map에 대한 입출력 타입을 설명해주는 것임.
let numbers: [Int] = [0, 1, 2, 3, 4]
var doubleNumbers: [Int] = [Int]()
doubleNumbers = numbers.map({ (number: Int) -> Int in number * 2 })
print(doubleNumbers)
// [0, 2, 4, 6, 8]
이 말은 즉슨, reduce 내 코드가
result + PizzaTopping.allCases.map { (topping) -> MainDish in MainDish.pizza(dough: dough, topping: topping)};
=
[] + [MainDish.pizza(dough: 피자도우.치즈크러스트, topping: 피자토핑.페퍼로니), MainDish.pizza(dough: 피자도우.치즈크러스트, topping: 피자토핑.치즈), MainDish.pizza(dough: 피자도우.치즈크러스트, topping: 피자토핑.베이컨)]
이렇게 된다는 이야기 ~
그러면 이제 한 바퀴 돈거니까
그 다음의 reduce는
result = [피자도우.치즈크러스트 + 토핑 3가지] dough = 피자도우.씬
이 되어서
위와 같은 과정을 또 거치면
그 다음 단계(마지막)에서는
result = [피자도우.치즈크러스트 + 토핑 3가지, 피자도우.씬 + 토핑 3가지] dough = 피자도우.오리지널
~~ 해서
reduce의 전 과정이 끝났을 땐
[MainDish.pizza(dough: PizzaDough.cheeseCrust, topping: PizzaTopping.pepperoni),
MainDish.pizza(dough: PizzaDough.cheeseCrust, topping: PizzaTopping.cheese),
MainDish.pizza(dough: PizzaDough.cheeseCrust, topping: PizzaTopping.bacon),
MainDish.pizza(dough: PizzaDough.thin, topping: PizzaTopping.pepperoni),
MainDish.pizza(dough: PizzaDough.thin, topping: PizzaTopping.cheese),
MainDish.pizza(dough: PizzaDough.thin, topping: PizzaTopping.bacon),
MainDish.pizza(dough: PizzaDough.original, topping: PizzaTopping.pepperoni),
MainDish.pizza(dough: PizzaDough.original, topping: PizzaTopping.cheese),
MainDish.pizza(dough: PizzaDough.original, topping: PizzaTopping.bacon)]
이렇게 되겠죠 ?
그러면 ,, 끝 !!
'iOS' 카테고리의 다른 글
제네릭과 표현 패턴 Generics and Expression Pattern 활용 예시 (0) | 2023.03.30 |
---|---|
struct의 subscript (feat. 설정자의 접근수준) (0) | 2023.02.01 |
prepareForReuse() 의 사용법 / 쓰는 이유 (0) | 2022.02.22 |
Delegate Pattern 서로 다른 클래스에 접근하기 / 동작하기 / 데이터 전달하기 (2) | 2021.07.13 |
스위프트에서 static 키워드란? 'static' in swift (5) | 2021.06.24 |
- Total
- Today
- Yesterday
- Objective-C
- 부가데이터
- 프래그먼트
- 전화연결하기
- swift
- 상태드로어블
- allcases
- 뷰페이저
- 표현패턴
- 터치리스너
- 비트맵버튼
- 인플레이터
- ios
- 안드로이드
- 어댑터
- subscript
- 액션바
- objc
- CaseIterable
- 전화걸기연결
- 제스처디텍터
- 다이얼연결
- 알림대화상자
- 스낵바설정
- 카카오톡열기
- 데이터
- 프래그먼트매니저
- 페이저타이틀스트립
- prepareforreuse
- 쉐이프드로어블
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |