티스토리 뷰
으아아아ㅏ아앙아아ㅏ아아아아!!!!!!!!!!!!!!!!!!!!!!!
이제 알겠습니다.
ㅎ아ㅏ하흐아하ㅏ아아ㅏ 넘좋아
제가 이때까지 코딩을 어떻게 했냐면요
var read = readLine()
if var read = read{
var arr = read.components(separatedBy: ",")
print(Int(arr[0])! + Int(arr[1])!) //끔찍한 부분
}
옵셔널 바인딩까지는 이해하겠습니다.
하지만 readLine이 String? 타입인 관계로 Int로 처리하려면 항상!!! 항상 Convert를 해주었어요.
솔직히 저 코드가 존재함으로써 뭔가 더러워보이지 않나요?
제 코드의 미의 기준에 상당히 어긋나는 코드였는데, 스택오버플로우를 가봐도 다 이렇게 Convert를 하더라구요
그래서 Swift라는 언어에 실망을 가지려는 찰나
발견했습니다. 하하하핳ㅎ하하하
아 너무 좋네요.
근데.. 기대하진마세요.....
⭐️map⭐️이라는 swift의 고차함수를 쓰니까요...
그래도 저는 한줄에 String을 Int로 바꿀 수 있다는 점이 너무 기뻐요 ㅠㅠㅠㅠㅠ
하하핳ㅎㅎ넘 조아
map
이제 알려드리겠습니다.
혹시 swift의 고차함수인 map을 아시나요?
간단하게 설명드리자면,
map
메소드는 제공된 클로저를 각 행렬 항목마다 적용한 후, 새롭게 매핑된 값들이 원래 행렬의 해당 값들의 순서와 같도록 배치된 새 행렬을 반환합니다.
map은 mapping에서 나온거랍니다 ㅎㅎ
[x1, x2, ... xn].map(f) -> [f(x1), f(x2), ... , f(xn)]
어떤 배열에 f라는 기준(클로저)으로 map을 해주니까 원래 배열의 모든 요소가 f라는 기준이 적용된 요소가 되었죠?
이것을 가능하게 해주는 것이 map입니다.
그럼 map을 어떻게 쓰는지 알아봅시다. 일단 함수를 쓰려면 그 함수의 원형을 보는게 가장 먼저겠죠?
Array.map(transform: T -> U)
transform 으로 넘기는 것은 클로져(Closure)인데 T는 원래 Array의 타입이고 U는 새롭게 만들 Array의 아이템 타입이라고 하네요.
여기서 제가 설정한 기준으로 새로운 Array를 만들게 되는거죠.
꼭 Array만 만들어지는 것은 아니에요!
예제를 통해 살펴볼까요?
우리가 궁극적으로 원하는 String에서 Int로 고치는 예제를 한번 같이 해봐요.
var read = readLine()
if var read = read{
var arr = read.components(separatedBy: " ").map({ (value : String) -> Int in return Int(value)! })
}
아...너무 ....길어서....스크롤..해야..보이네요..캡쳐를 해보겠습니다.
일단 map은 받은 배열의 모든 원소를 봅니다.
일단 우리가 주는 (위에서 T타입인) 타입은 String이죠?
String을 Int로 고쳐야 하니까요. 그러니까 ->는 리턴을 의미합니다.
-> 뒤에 Int가 적혀있네요?
그럼 (value : String) -> Int이라는 말은
String으로 배열을 받는데, Int형 배열로 반환해주겠다..라는 소리겠네요.
근데 이렇게만 하면 map이 아니겠죠? 어떤 '기준'을 설정해줘야해요.
모든 요소는 이 기준에 따라 바뀌게 되겠죠.
in return은 '어 리턴해주긴 하는데 이 뒤에 있는 거 적용시켜서 리턴해주라' 이소리에요.
그렇다면 in return Int(value)!이라는 소리는
"어 이 기준에 따라서 배열 하나 리턴해주라." 라는 겁니다.
근데 우리가 리턴할 타입은 Int죠? 그러니까 각 요소를 Int로 Convert해주어야 하는겁니다.
실제로 저 Int로 바꿔주지 않게 되면, 그러니까
이렇게 해주면,
String타입을 변환할 수 없다고 그러죠? 클로져의 결과타입인 Int로요.
ㅎㅎ자 그럼 정상적인 코드로 돌아가서, 실행시켜보면
짠 이렇게 잘 나오게 된답니다. map은 배열을 리턴해주니, 배열형태로 나오게 되었죠?ㅎㅎ
이렇게 한번에 String을 주어진 separator로 나눠주고, 매핑까지 한번에 할 수 있게 되었어요.
특정한 값만 얻어오고 싶으면 arr[인덱스]를 해주면 되겠죠?
근데.... 전 세계 사람들은 다들 똑같은 마음이었다는 겁니다,
map이 쓰기 짱어렵게 생겼따는 사실
언제 저거 적고있어 ㅡㅡ
이래서 애플은 map을 축약하고 또 축약할 수 있도록 만들어주었습니다!!!!
Xcode가 짱 똑똑해서 추론을 잘하거든요. 이 Xcode가 축약을 가능하게 해준답니다.
● 축약 - 1
일단 우리가 String타입의 배열을 넘겨주죠?
하지만 Xcode도 압니다. 보면 readLine은 String이니까..그래서 타입을 꼭 적어주지 않아도 됩니다.
var arr = read.components(separatedBy: " ").map({ (value) -> Int in return Int(value)! })
오 드디어 이제 한눈에 볼 수 있게 되었군요 ㅎㅎ작아졌지만...
저 value뒤에 String이라는 키워드가 없어진 것. 보이시나요?
● 축약 - 2
자 여기서 또 축약 해봅시다.
바로 in return 인데요, Xcode는 짱 똑똑해서 압니다. 이 뒤에는 조건이 들어간다는것을...
조건이 만약 한줄이라면,(두 줄 이상일때는 return을 써줘야합니다.)
그래서 in return대신에 in만 써주어도 '아 이뒤에는 조건이 나올 건가봐!!'하고 알 수 있답니다.
그래서
var arr = read.components(separatedBy: " ").map({ (value) -> Int in Int(value)! })
in뒤에 return이 사라진 것 보이시나요?ㅎㅎ
자 이게 끝이냐
아닙니다. 오늘 축약의 끝을 보실 수 있을 겁니다....
● 축약 - 3
자, 또 축약을 한번 더 해보자면
in 뒤에서 우리는 Int로 Convert를 해주게 되는데, ㄷ또 우리 짱 똑똑한 Xcode는 아는거죠..
아 내가 반환할 배열은 Int형 타입이겠구나...
그럼 이제 좀 추측이 가시나요?
var arr = read.components(separatedBy: " ").map({ (value) in Int(value)! })
!!! 두둥 -> 라는 기호와 Int가 없어졌네요. -> Int자체가 Int타입을 리턴할거야! 라는 것이니
둘다 없어도 되는거겠죠.
자.. 정말 많이 줄어들었죠? ㅎㅎㅎ 여기서 더 축약을 할 수 있다면 믿으시겠어요? ㄷㄷ
자 일단 중복이 보입니다. 네. value요 아니 누가 두번 쓰고 싶겠어요 ㅎㅎ
앗 그럼
var arr = read.components(separatedBy: " ").map({ Int(value)! })
이렇게 줄일 수 있는건가요?????!! 하실 수도 있지만, 음 아닙니다. 위 코드는 오류를 내게 될텐데요,
일단 value라는 것을 정의하지 않았으니 이 value가 뭔지 모르는겁니다.
● 축약 - 4
그래서 우리 애플은 극단적으로 $0이라는 기호를 사용하게 됩니다.
$0은 그냥 value를 기호로 나타낸 것 뿐, 똑같은 기능을 합니다.
var arr = read.components(separatedBy: " ").map({ Int($0)! })
짠~~ㅎㅎㅎ어때요 ㄷㄷ 또 여기서 더 축약이 가능하다고 하시면 믿으실건가요?ㅎㅎㅎㅎ
● 축약 - 5
var arr = read.components(separatedBy: " ").map() { Int($0)! }
저렇게 클로저를 감싼 ()를 앞으로 가져올 수 있답니다.
한번 더 축약이 가능하다고 하면 믿으실건가요 ㄷㄷ?
● 축약 - 6
var arr = read.components(separatedBy: " ").map{ Int($0)! }
가능은 한데요, 저 ()를 없앨 수 있습니다. ㄷㄷ 이정도면 축약의 끝판왕 아닌가요?
자, 실행해보면
짠~~~ㅎㅎㅎ
자..그런데 map은 치명적인 단점을 가지고 있는데요, 뭘 것 같으세요?
네... 누군가 제 코드를 봤을 때 이게 뭔소린지 모른다는 겁니다...................
그래서 극단적으로 저렇게 축약의 축약은 자제하시는 것이 좋아요. 특히 Swift를 이제 갓 배우시는 분들에게는 비추드립니다(저한테 하는말)
스택오버플로우 가보시면 $0이 난무하는 것을 볼 수 있는데요, 이 축약된 클로져의 원래형태가 어떤것이였는지 연습하는 것이 좋아요 :) 야곰님이 해주신 말씀이랍니다.
저는 일단 하나도 축약하지 않고 써볼려구요 ㅎㅎㅎㅎ
그렇게 연습하면서 차차 축약을 해나가는거죠 흫ㅎ
var read = readLine()
if var read = read{
var arr = read.components(separatedBy: ",")
print(Int(arr[0])! + Int(arr[1])!) //끔찍한 부분
}
이 코드가
var read = readLine()!
var arr = read.components(separatedBy: " ").map({ (value : String) -> Int in return Int(value)! })
print(arr[0]+arr[1])
이렇게 바뀔 수 있겠네요 ㅎㅎ
readLine을 강제로 받아오면 옵셔널 바인딩을 하면 안된답니다. ㅎㅎ 더 깔끔해져서 이렇게 해봤어요.
아무튼 오늘의 주제는 String을 Int로 한줄로 변환하는 방법에 대해서 쓸려고 시작한건데.. map의 개념까지 쓰게 됐네요 XD
도움이 되었으면 좋겠어요 😆
'Swift' 카테고리의 다른 글
Swift3 ) String쪼개기 (1) | 2017.05.29 |
---|---|
Swift3 -) for문(for loop) / for문과 stride 같이쓰기 (1) | 2017.05.22 |
Xcode - swift 파일 여러개 놓고 코딩하는 법 (2) | 2017.05.20 |
Xcode - statements are not allowed at top level오류 해결법 (8) | 2017.05.18 |
Swift3 ) Swift에서 키보드 입력 받는법(user input) (7) | 2017.05.17 |
- fastlane
- swift tutorial
- iOS delegate
- np-hard
- 스위프트 문법
- swift delegate
- ios 13
- Swift
- actor
- Xcode
- swift sort
- FLUTTER
- SwiftUI
- swift3
- WWDC
- IOS
- np-complete
- github
- 제이슨 파싱
- UIBezierPath
- 회고
- WidgetKit
- swift 공부
- Accessibility
- Git
- 피아노
- swift array
- Combine
- WKWebView
- 스위프트
- Total
- Today
- Yesterday