[TIL] 옵셔널 + 관련 알고리즘 풀이

한철희·2024년 3월 5일
0

TIL

목록 보기
2/57

오늘 학습한 내용중에선 옵셔널 관련 내용을 정리해보자

일단 옵셔널이 무엇이냐?

var optional: Int? = 404

이거다
잘 보면 Int 타입 옆에 ?가 붙어있는게 보일것이다
저게 옵셔널 변수를 선언한것이다.
옵셔널 변수는 값이 있을 수도, 없을 수도 있는 변수다.

예제를 통해 살펴봅시다

// 첫번째 예시
var example: Int = 4
print(example)

// 두번째 예시
var example: Int
print(example)

위의 코드를 보자
첫번째 예시는 4라는 값이 출력될 것이다. 이건 쉽게 예측할 수 있다
그럼 두번째 예시는 어떻게 될까?
아마 에러가 발생할 것이다
왜냐하면 example이라는 변수에 값이 할당되어 있지 않기때문에 출력할 값이 없기 때문이다.

그럼 이런 상황을 안 만드면 되지 않아? 라고 생각할 수 있지만
실제로 서비스를 제작하다 보면 아직 값이 할당되지 않은 상태로 변수를 만드는 경우가 생긴다.
이런 경우에 쓰는것이 옵셔널인 것이다.

var example: Int?
print(example)

위의 두번째 예시에 옵셔널 변수만 추가한 것이다.
이제 실행 결과를 보면
에러가 뜨지않고 nil이 뜨게된다.
참고로 nil은 다른 언어의 null이나 NULL과는 다른 개념이다. nil은 엄연히 할당된 값으로 여겨진다.

아무튼 이런 옵셔널 변수는 실제로 사용하려면 다른 변수들과 다르게 언래핑 이라는 과정을 거치고 사용해야한다.
이 과정은 택배 상자를 언박싱 하는것에 비유할 수 있다
택배 상자를 개봉했을 때 안에 물건이 있을 수도 있지만 없을수도 있다
그리고 물건이 있다면 사용하기 위해서 상자를 개봉 해야한다.
언래핑 방법에는 크게 옵셔널 바인딩강제 언래핑이 있다

옵셔널 바인딩은 또 if letguard let으로 나눌수있다
예제 코드로 확인해 보자

if let

let ticketCounts: Int? = 3
if let ticket = ticketCounts {
    print (ticket)
}

guard let

let x : Int? = 10
//
func opbinding() {
    guard let x = x else { return }
    print(x)
}

둘이 비슷해 보이지만 내가 공부한바로
차이점은 구문내에서 언래핑한 변수를 if let은 지역 변수로만 사용이 가능하고 guard let은 전역변수로 사용 가능하다는 점이다.
또, guard문은 if문과 다르게 뒤에 항상 else가 붙어 다니며 else구문 내에서 return, break, continue 같은 제어구문을 사용한다.


이제 강제 언래핑에 대해서 보자
바로 예시 코드를 보자

let number = Int("42")!
print(number)
//
let address: String? = nil
print(address!)

옵셔널 바인딩과 다르게 굉장히 심플하다
언래핑 하고자 하는 값에 !만 붙여주면 된다.
대신 강제 언래핑은 잘못 사용하면 프로그램에 크래시가 날 수 있기 때문에 nil값이 확실히 아닌 경우에만 사용해야한다.


그리고 이날 프로그래머스 문제 풀이 중 옵셔널 관련 문제가 나와서 같이 작성해두려고 한다.
https://school.programmers.co.kr/learn/courses/30/lessons/12919
링크를 같이 첨부했다

func solution(_ seoul:[String]) -> String {
    var idx = seoul.firstIndex(of: "Kim")!
    return "김서방은 \(idx)에 있다"
}

이게 내 첫번째 풀이인데 배열의 인덱싱을 활용해서 풀이했다 firstIndex(of:)를 쓰면 나오는값이 옵셔널이여서 활용하기위해 강제언래핑으로 언래핑을 진행했다.
근데 내가 아까 위에서 언급했다시피 nil값이 나올 수도 있는 상황에서는 강제 언래핑을 지양해야한다.
나는 문제 제한 사항에 <"Kim"은 반드시 seoul 안에 포함되어 있습니다.> 라는 문구를 보고 강제 언래핑을 사용했다.

만약 이 문구가 없었고 언래핑을 해야하는 상황이라면 아래 같이
if let이나 guard let으로 풀이 했을것이다

if let

func solution(_ seoul: [String]) -> String {
    guard let idx = seoul.firstIndex(of: "Kim") else {
        return ""
    }
    let result = "김서방은 \(idx)에 있다"
    return result
}

guard let

func solution(_ seoul: [String]) -> String {
    guard let idx = seoul.firstIndex(of: "Kim") else {
        return ""
    }
    let result = "김서방은 \(idx)에 있다"
    return result
}

이런 식으로 말이다
다른 사람의 강제 언래핑을 활용한 풀이를 봤는데 굉장히 간단하게 잘 풀이해서 첨부해본다

func solution(_ seoul:[String]) -> String {
    return "김서방은 \(seoul.firstIndex(of: "Kim")!)에 있다"

프로그래머스 풀이를 보다보면 구문을 되게 간단하게 작성해서
풀이하는 분들이 많은것같다.

내 방법 말고 단순히 배열의 값을을 Kim과 대조하여 푸는 방법도 봤다.

func solution(_ seoul:[String]) -> String {
    for i in 0..<seoul.count {
        if seoul[i] == "Kim" {
            return "김서방은 \(i)에 있다"
        }
    }
    return ""
}

이 방법인데 둘 다 해당 인덱스를 찾자 마자 위치를 반환하므로 효율성 측면에서는 비슷할것같다.

profile
초보 개발자 살아남기

0개의 댓글