Equatable и Hashable — зачем? Почему ключ Dictionary должен быть Hashable?
Суть
Equatable даёт оператор == — «эти два значения одинаковы». Hashable расширяет Equatable и добавляет hash(into:) — сворачивание значения в число через Hasher. Dictionary и Set требуют Hashable от ключа/элемента, потому что ищут не перебором, а по хешу: хеш → индекс бакета, затем == для разрешения коллизий. Это даёт O(1) в среднем (в худшем случае, при массовых коллизиях, — O(n)).
struct User: Hashable { // == и hash(into:) синтезируются по всем полям
let id: Int
let name: String
}
struct Tag: Hashable { // своя семантика: регистр не важен
let value: String
static func == (l: Tag, r: Tag) -> Bool {
l.value.lowercased() == r.value.lowercased()
}
func hash(into hasher: inout Hasher) {
hasher.combine(value.lowercased()) // равные → равный хеш
}
}
let tags: Set<Tag> = [Tag(value: "Swift"), Tag(value: "swift")]
print(tags.count) // 1
var ages: [User: Int] = [:]
ages[User(id: 1, name: "Ann")] = 30
Продолжение ответа с кодом и уточняющими вопросами интервьюера — в приложении DevPrep.
Полный ответ — в DevPrep