Hashable - ehrldyd15/Swift_Skills GitHub Wiki

Hashable

1. ํ•ด์‹œ(Hash)๋ž€?

ํŠน์ • Key - Value๋ฅผ ์ €์žฅํ•œ๋‹ค๊ณ  ํ•˜๋ฉด

ํ•ด๋‹น Key๋ฅผ ํ•ด์‹œ ํ•จ์ˆ˜๋ž€ ๊ฒƒ์„ ํ†ตํ•ด ํ•ด์‹œ๋ฅผ ํ•˜๊ณ ,

๊ฒฐ๊ณผ ๊ฐ’์ธ ํ•ด์‹œ ์ฃผ์†Œ ๊ฐ’์— ํ•ด๋‹นํ•˜๋Š” ํ•ด์‹œ ํ…Œ์ด๋ธ” ์Šฌ๋กฏ์— Value๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-07-11 แ„‹แ…ฉแ„’แ…ฎ 2 36 13

์ฆ‰, Key ๊ฐ’์„ ํ•ด์‹ฑ ํ•จ์ˆ˜์— ๋„ฃ์–ด ํ•ด์‹œ ํ•˜์—ฌ ๋ฐฐ์—ด์˜ ์ฃผ์†Œ๊ฐ’(ํ•ด์‹œ ์ฃผ์†Œ๊ฐ’)์„ ์–ป๊ณ , ๊ทธ ์ฃผ์†Œ๊ฐ’์— ๋งž๋Š” index์— Value๊ฐ’์„ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ์•„๋ž˜์ฒ˜๋Ÿผ Key๊ฐ’์œผ๋กœ ๊ธฐ๋ณธ ์ž๋ฃŒํ˜•(Int, String)์„ ์“ธ ๊ฒฝ์šฐ

let myDict: [String: Int] = ["ABC": 28]

Equatable๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๊ธฐ๋ณธ ์ž๋ฃŒํ˜•์€ ์ปดํŒŒ์ผ๋Ÿฌ์— ์˜ํ•ด Hashable ํ”„๋กœํ† ์ฝœ์ด ์ž๋™์œผ๋กœ ์ฑ„ํƒ๋œ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋งŒ์•ฝ ๊ตฌ์กฐ์ฒด๋กœ ๋งŒ๋“ค๊ฒฝ์šฐ

struct Human {
    let name: String
    let age: Int
}
 
let myDict: [Human: Int] โŒ // Type 'Human' does not conform to protocol 'Hashable'

Human ๋‚ด๋ถ€์— name, age๋ž€ ํ”„๋กœํผํ‹ฐ๊ฐ€ ๊ธฐ๋ณธ ์ž๋ฃŒํ˜•์ด์ง€๋งŒ,

์–ด๋–ค ๊ฐ’์œผ๋กœ ํ•ด์‹œ๋ฅผ ํ•ด์•ผํ• ์ง€ ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

(Hashable ํ”„๋กœํ† ์ฝœ์„ ์ค€์ˆ˜ํ•˜์ง€ ์•Š์•˜๋‹ค๋Š” ์—๋Ÿฌ์ด๋‹ค.)

๋”ฐ๋ผ์„œ ๋”•์…”๋„ˆ๋ฆฌ์—์„œ Key๊ฐ’์€ ๋ฌด์กฐ๊ฑด ์–ด๋–ค ํ”„๋กœํผํ‹ฐ๋ฅผ ํ•ด์‹œ ํ• ์ง€์— ๋Œ€ํ•ด ์ •์˜ํ•ด์•ผํ•˜๋Š”,

๋ฐ”๋กœ Hashable์ด๋ž€ ํ”„๋กœํ† ์ฝœ์„ ์ค€์ˆ˜ํ•˜๊ณ  ์žˆ๋Š” ํƒ€์ž…๋งŒ์ด ๊ฐ€๋Šฅํ•œ ๊ฒƒ์ด๋‹ค.

(๋”•์…”๋„ˆ๋ฆฌ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํ•ด์‹œ ํ…Œ์ด๋ธ”์„ ์“ฐ๋Š” Set์„ ์“ธ ๋•Œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋‹ค.)

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-07-11 แ„‹แ…ฉแ„’แ…ฎ 2 45 01

Hashable ํ”„๋กœํ† ์ฝœ์€ ์œ„์™€ ๊ฐ™์ด ์ƒ๊ฒผ๋‹ค.

hashValue๋Š” ๋”์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ”„๋กœํผํ‹ฐ๋ผ๊ณ  ํ•˜๊ณ ,

ํ•„์š”ํ•  ๊ฒฝ์šฐ hash(into:) ํ•จ์ˆ˜๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

๋˜ํ•œ Hashable์€ ์ž์ฒด์ ์œผ๋กœ Equatable์ด๋ž€ ํ”„๋กœํ† ์ฝœ์„ ์ค€์ˆ˜ํ•˜๊ณ  ์žˆ๋‹ค.

2. ๊ตฌ์กฐ์ฒด, ํด๋ž˜์Šค, ์—ด๊ฑฐํ˜•์—์„œ Hashable์„ ์ฑ„ํƒํ•˜๋Š” ๋ฐฉ๋ฒ•

2-1 ๊ตฌ์กฐ์ฒด

Equatable๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋งŒ์•ฝ ๊ตฌ์กฐ์ฒด ๋‚ด ํ”„๋กœํผํ‹ฐ๊ฐ€ ๋ชจ๋‘ ๊ธฐ๋ณธ ์ž๋ฃŒํ˜•์ด๋ผ๋ฉด,

Hashable์„ ์ฑ„ํƒํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ์ถ”๊ฐ€ ๊ตฌํ˜„ ์—†์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

struct Human: Hashable {
    let name: String
    let age: Int
}
 
let myDict: [Human: Int] = [:]  

์ด๋Ÿฐ ์‹์œผ๋กœ Human์ด๋ผ๋Š” ๊ตฌ์กฐ์ฒด๋ฅผ ๋”•์…”๋„ˆ๋ฆฌ์˜ Key๋กœ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

2-2 ํด๋ž˜์Šค

ํด๋ž˜์Šค๋Š” Hashable์ด๋ž€ ํ”„๋กœํ† ์ฝœ์„ ์ค€์ˆ˜ํ•˜๋Š” ๊ฒƒ ์™ธ์—๋„ ์ง์ ‘ hashํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

๋‹คํ–‰์Šค๋Ÿฝ๊ฒŒ๋„ combine์ด๋ผ๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•˜์—ฌ ์‰ฝ๊ฒŒ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

class Human {
    let name = "ABC"
    let age = 28
}
 
extension Human: Hashable {
    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
        hasher.combine(age)
    }
}
 
let myDict: [Human: Int] = [:]

์ด๋ ‡๊ฒŒ! hash ๋ฉ”์„œ๋“œ๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์ฃผ๋Š”๋ฐ,

์ด๋•Œ hasher.combine์ด๋ž€ ๋ฉ”์„œ๋“œ์— ์–ด๋–ค ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ•ด์‹œํ•  ๊ฒƒ์ธ์ง€๋ฅผ ๋„ฃ์–ด์ค€๋‹ค.

ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ฉด combine์—๋Š” ํ•ด๋‹น ํƒ€์ž…์˜ ๋ชจ๋“  ์ €์žฅ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๋˜ํ•œ, combine ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌํ•˜๋Š” ํ”„๋กœํผํ‹ฐ๋Š” ๋ฐ˜๋“œ์‹œ Hashable์„ ์ค€์ˆ˜ํ•˜๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค.

(์œ„์—์„œ name, age๋Š” ๊ธฐ๋ณธ ์ž๋ฃŒํ˜•์ด๊ณ , ์ž๋™์œผ๋กœ Hashable์„ ์ค€์ˆ˜ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ„์ฒ˜๋Ÿผ combine์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ ํ•  ์ˆ˜ ์žˆ๋‹ค.)

๊ทธ๋Ÿฌ๋‚˜

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-07-11 แ„‹แ…ฉแ„’แ…ฎ 3 01 19

์œ„์™€ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

Hashable์€ Equatable์„ ์ฑ„ํƒํ•˜๊ณ  ์žˆ์–ด์„œ ์ž๋™์œผ๋กœ ์ œ๊ณต๋˜์ง€ ์•Š๋Š” ํด๋ž˜์Šค์˜ ๊ฒฝ์šฐ ์ง์ ‘ ๊ตฌํ˜„์ด ํ•„์š”ํ•˜๊ธฐ ๋–„๋ฌธ์ด๋‹ค.

class Human {
    let name = "ABC"
    let age = 28
}
 
extension Human: Hashable {
    static func == (lhs: Human, rhs: Human) -> Bool {
        return lhs.name == rhs.name && lhs.age == rhs.age
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
        hasher.combine(age)
    }
}
 
let myDict: [Human: Int] = [:]

์ด์ œ์•ผ ๋ณด๋กœ์†Œ Human์ด๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ Hashable ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•ด์•ผ ํ•˜๋Š” ์ž๋ฃŒํ˜•์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ํด๋ž˜์Šค์—์„œ Hashable์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, hash ๋ฉ”์†Œ๋“œ๋ฅผ ์ง์ ‘๊ตฌํ˜„ + "==" ๋ฉ”์†Œ๋“œ ์ง์ ‘๊ตฌํ˜„ ํ•ด์•ผ ํ•œ๋‹ค.

2-3 ์—ด๊ฑฐํ˜•

์—ฐ๊ด€๊ฐ’์ด ์—†๋Š” ์—ด๊ฑฐํ˜•

enum Gender {
    case male
}
 
let myDict: [Gender: Int] = [:]

Hashable์„ ์ฑ„ํƒํ•˜์ง€ ์•Š์•„๋„ ์ž๋™์œผ๋กœ ๊ตฌํ˜„์ด ๋œ๋‹ค.

์—ฐ๊ด€๊ฐ’์ด ์žˆ๋Š” ์—ด๊ฑฐํ˜•

enum Gender: Hashable {
    case male(age: Int)
}
 
let myDict: [Gender: Int] = [:]

Hashable์„ ์ฑ„ํƒํ•œ๋‹ค๊ณ  ์„ ์–ธํ•ด์ฃผ๊ณ ,

์—ฐ๊ด€๊ฐ’์˜ ํƒ€์ž…์ด(Int)์ด ๋ชจ๋‘ Hashable์„ ์ฑ„ํƒ(๊ตฌํ˜„)ํ•˜๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์ฐธ๊ณ ์ž๋ฃŒ

https://babbab2.tistory.com/149?category=828998