문제설명
자연수 N이 주어지면, N의 각 자릿수의 합을 구해서 return 하는 solution 함수를 만들어 주세요.
예를들어 N = 123이면 1 + 2 + 3 = 6을 return 하면 됩니다.
풀이
그냥 처음에는 반복문 돌리면서 , 혹은 reduce로 한번에 배열을 짤라준다음 각 원소들을 Int로 바꿔줘서 더해주면 되겠구나 싶었는데, 다음과 같은 에러가 발생했다.
이유인 즉슨, Array(String(n))
을 반복문 돌려서 하나씩 볼때는 각각의 value가 Character 타입이 되는데, Character Type일때는 Int로 전환이 불가능하다는 이야기였다.
첫번째 방법
wholeNumberValue
를 사용하는 것이다.두번째 방법
- Character -> String
- String -> Int
이렇게 두 단계를 거쳐서 해줄 수 있는 해결책이다.
import Foundation class Solution { func addLocation(_ n: Int) -> Int { return Array(String(n)).reduce(0) { $0 + Int(String($1))! } } } let solution = Solution() print(solution.addLocation(1234))
Stirng으로 한번 묶어준 친구를 한번 더 Int로 묶어주면 정상적으로 실행이 된다.
여기 자세히 보시면은
$0 + Int(String($1))!
!로 강제 언래핑을 해준 것을 볼 수 있다. Int(String(($1))을 !없이 수행하게 되면 이게
Optional<Int>
로 되기 때문에
- 이거 nil 안나오는거로 줄게! +
- 안에 들어오는 String($1)는 분명 너가 올바른 값으로 반환할 수 있는 친구를 넣어줄거야!
라고 약속한 것이라고 보시면 될 것 같다.
라고 의문점이 들었는데 알아보니
String($1)은 단순히 Character를 문자열로 변환해주는 친구라서,Optional<Type>
가 아니라 확정된 타입으로 반환해주기 때문인데,즉 크래시 될일이 없기때문에 컴파일러 입장에서도 옵셔널로 인지할 필요가 없는 것으로 판단한다.
즉 String의 반환타입은 non-optional이기 때문, 이것으로 얻은 새로운 정보는 함수에 따라 non-optional인 함수와 그렇지 않은 함수가 구분되는구나, 그것으로 인해서 이게 옵셔널로 값을 인지하는지 안하는지 알아낼 수가 있구나 싶었다.
let stringValue = String(123) let intValue = Int("123") print(type(of: stringValue)) // String print(type(of: intValue)) // Optional<Int>
보시면은 Int() 메소는 Optional 타입을 반환한다. 인자값에 사용자가 이상한 집어넣었을지 모르니 일단
문자열을 정수로 변환하는 과정에서 변환이 실패할 수 있기 때문에Optional<Int>
타입을 반환하기로한 optional함수인것이다. 언제든지 nil을 반환할 수 있게끔, nil이 떠도 괜찮게 Optional을 고수하고 있다.
컴파일러에게 나는 Int()잘 굴러가게 제공할게~
개발자인 우리가 컴파일러에게 이 값은 nil이 리턴되지 않게끔 내가 잘 약속 지킬게!라고 보증하는 것이다.
라고 선언한다고 보시면 이해하기 쉽다. 그런데 배신하고!하면서 Int()안에 "ABC"같이 소화하지 못하는 파라미터를 넣어주면 이제 에러가 발생할 것이다.
대신, 이렇게 약속을 잘지키면 아래처럼
let optionalValue = Int("123) let intValue = Int("123")! print(type(of: optionalValue)) // Optional<Int> print(type(of: intValue)) // Int
!를 붙여줬으면 그냥 Int값으로 Swift가 보답을 해줄것이다..
놀랍게도..!
String()변환은 일반적으로 실패할 가능성이 없다고한다. 어떤 타입이던지 잘 String()으로 반환될 수 있기 때문에 강제언래핑 같은 거를 활용하지 않더라도 이거는 그냥 확실하게 String으로 나오는것이다.
Optional<String>
이렇게 반환되지 않는다. 그래서non-optional
이고, 언래핑이 필요하지 않다.
예시
let emptyString = String() // "" nil대신 그냥 빈문자열이 반환됨 let stringFromInt = String(123) // "123" let stringFromChar = String("A") // "A" let stringFromArr = String([1,2,3]) // "[1,2,3]" 배열마저 이렇게 문자열로 잘 바뀜
결론적으로
import Foundation class Solution { func addLocation(_ n: Int) -> Int { return Array(String(n)).reduce(0) { $0 + Int(String($1))! } } } let solution = Solution() print(solution.addLocation(1234))
따라서 String($1)은 옵셔널이 아니므로 강제 언래핑(!)이 필요 없기때문에 Int()에 해당하는 언래핑 ! 한번으로 해결되는 것을 확인할 수 있었습니다!
느낀점
엄청나게 쉬운 응애 문제였는데, 모든게 좀 새로워서 정리하느라 좀 시간을 많이 잡아먹은 것 같다. 이번에 Optional에 대해서 좀 맛보기처럼 알아봤는데, 이제 다음에는 Optional관련해서 좀 더 길게 포스팅을 해봐야겠다고 생각을 했다. (블로그 뒤적이면서 얻은 정보는, swift의 Optional이 C언어의 포인터처럼 swift의 핵심격으로 취급되는것 같더라. 원래 헷갈리는 개념이구나를 알게되었고, 좀 더 깊게 해봐야할 것 같다.