Menu
Coddy logo textTech

Hashable

Parte de la sección Programación orientada a objetos del Journey de Swift de Coddy. Lección 40 de 57.

Hashable permite almacenar valores en un Set o utilizarlos como claves de Dictionary. Un hash es un número calculado a partir del valor, que se utiliza para encontrarlo rápidamente. Las estructuras y enumeraciones cuyas propiedades son todas Hashable obtienen esta conformidad al declararla:

struct Point: Hashable {
    let x: Int, y: Int
}

var visited: Set<Point> = []
visited.insert(Point(x: 0, y: 0))
visited.insert(Point(x: 1, y: 0))
visited.insert(Point(x: 0, y: 0))
print(visited.count)
print(visited.contains(Point(x: 1, y: 0)))

Salida:

2
true

Los valores hashables son buenas claves de diccionario, por ejemplo, para contar las apariciones de valores estructurados:

struct Pair: Hashable {
    let from: String, to: String
}

let trips = [Pair(from: "A", to: "B"), Pair(from: "B", to: "C"), Pair(from: "A", to: "B")]
var counts: [Pair: Int] = [:]
for t in trips { counts[t, default: 0] += 1 }
print(counts[Pair(from: "A", to: "B")]!)

Salida:

2

Hashable se basa en Equatable. Cuando == compara solo algunas propiedades, el hash debe usar las mismas propiedades, lo que se hace en hash(into:). De lo contrario, dos valores iguales podrían obtener hashes diferentes y un conjunto conservaría ambos:

struct User: Hashable {
    let id: Int
    var name: String

    static func == (lhs: User, rhs: User) -> Bool { lhs.id == rhs.id }
    func hash(into hasher: inout Hasher) { hasher.combine(id) }
}

let users: Set<User> = [User(id: 1, name: "Ada"), User(id: 1, name: "Ada L."), User(id: 2, name: "Bo")]
print(users.count)

Salida:

2

La regla que debes recordar: los valores que son iguales deben tener hashes iguales. Los valores hash cambian entre ejecuciones del programa, así que nunca los almacenes ni los imprimas; úsalos únicamente mediante conjuntos y diccionarios.

// valores iguales -> hashes iguales (requerido)
// valores diferentes -> usualmente hashes diferentes
func hash(into hasher: inout Hasher) {
    hasher.combine(id)          // exactamente las propiedades que == compara
}
challenge icon

Desafío

Fácil

Un robot en una cuadrícula se mueve U, D, L, R un paso a la vez desde (0, 0). Haz que Position (x, y) sea Hashable y completa explore(_:), que devuelve tres líneas: visited 5 cells (el número de posiciones distintas, incluida la inicial), revisits 2 (movimientos que terminaron en una celda ya visitada) y most visited (0, 0) x3 (la celda a la que se entró más veces, contando la posición inicial como una visita; la primera que alcanza ese número gana los empates).

El código proporcionado lee una línea de movimientos e imprime cada línea devuelta.

Tu código va en Position.swift y Functions.swift. main.swift contiene el código proporcionado de entrada/salida y no se puede editar.

Pruébalo tú mismo

// Código de entrada/salida suministrado: déjalo tal como está
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in explore(input[0]) { print(line) }
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Playground de Swift