[Swift] Set 컨트롤하기

[Swift] Set 컨트롤하기

Hashable과 Equatable을 채택하는 이유

  • 부족한 지식으로 공부하며 적어가고 있습니다. 틀린 부분이 있다면 댓글로 적어주시면 더 공부 후에 수정하겠습니다!

우리가 컨트롤 해야하는 것은 마인트 컨트롤만 있는건 아니다.

이번엔 Swift의 Set 컨트롤을 해보자.


struct TestStruct {
    let n: Int
    var str: String
}

TestStruct를 Element로 갖는 Set을 가지려면 어떻게 해야할까?

-> 먼저 Hashable을 채택해야한다.

잠깐 여기가 시작이자 끝이다. 왜 Hashable을 채택해야하며 Hashable이 어떤 역할을 하는지 알아보자.

Hasable은 hash라는 함수를 통해 hasher라는 고유의 값을 만들어 낸다.

이 hasher의 고유한 값이 그 값이 Set에 빠르게 접근할 수 있는 키워드가 된다.

    func hash(into hasher: inout Hasher) {
        haser.combine(/*변수*/)
    }

위 함수를 넣어주면 사용자가 직접 hasher에 어떤 변수를 어떤 순서로 만들지 결정할 수 있다.

하지만 서로 다른 값을 갖고 있는 TestStruct1TestStruct6이 hash 함수를 이용하면 같은

hasher를 갖을 수 있다. 우린 이걸 Hash 충돌이라고 한다.

[* Hash 충돌 해결에 대해서는 나중에 정리하자.]

Hash 충돌이 일어나면 Set는 충돌된 두 값이 같은 값인지 다른 값인지 판단해야한다.

그렇기에 Hashable은 Equatable을 채택하고 있다.

같은 값이면 같다고, 다르면 다르다고 알려줘야하기에

static func == (lhs: TestStruct, rhs: TestStruct) -> Bool {
        /* 코드 기입 */
    }

함수를 기입하면 된다.


실전

struct TestStruct {
    let n: Int
    var str: String
}

만약 TestStruct에서 숫자 n 만 같으면 똑같은 값이야! 라고 설정하고 싶다.

그럼 우선 hasher가 n에 대해서만 관련 짓도록 만들어 Hash 충돌을 만들어야 한다.

struct TestStruct: Hashable {
    let n: Int
    var str: String

    func hash(into hasher: inout Hasher) {
        hasher.combine(n)
    }
}

이렇게 n만 hasher에 combine 이뤄지면 hasher가 같기에 충돌이 일어날 것이다.

그럼 충돌 이후 두 값이 같음을 보여야 한다.

struct TestStruct: Hashable {
    let n: Int
    var str: String

    func hash(into hasher: inout Hasher) {
        hasher.combine(n)
    }

    static func == (lhs: TestStruct, rhs: TestStruct) -> Bool {
        return lhs.n == rhs.n
    }
}

==함수를 적어 hasher가 n만 비교하는 것을 보여준다.

let testStruct1 = TestStruct(n: 3, str: "AAA")
let testStrcut2 = TestStruct(n: 3, str: "BBB")

var set = Set<TestStruct>([testStruct1, testStrcut2])

print(set) // [SwiftTest.TestStruct(n: 3, str: "AAA")]

testStruct1과 testStruct2가 Set에서는 같디고 판단되어 1개의 값만 저장 됨을 알 수 있다.