Uso de KeyPaths en colecciones
Ordene y transforme colecciones mediante rutas de claves.
Uso de KeyPaths en colecciones es una lección gratuita de Swift Academy en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Swift Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Swift Academy incluye 4 lecciones en total.
Las rutas de claves destacan en las colecciones
Las operaciones de colecciones como map, sorted y filter a menudo solo leen una propiedad de cada elemento. Las rutas de claves permiten expresar esa intención sin escribir un closure.
Swift acepta una ruta de claves en cualquier lugar donde se espera una función de un argumento que devuelva un valor, porque una ruta de claves se puede usar como una función de Root a Value.
struct Person {
let name: String
let age: Int
}
let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
let names = people.map(\.name)
print(names)Notación abreviada de map con una ruta de claves
Pasar map(\.property) equivale a escribir un closure que devuelve esa propiedad, pero es más corto y claro. La barra invertida y el punto iniciales permiten que el compilador infiera el tipo del elemento.
Compare las dos formas siguientes; producen el mismo resultado.
struct Person {
let name: String
let age: Int
}
let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
let closureForm = people.map { $0.age }
let keyPathForm = people.map(\.age)
print(closureForm)
print(keyPathForm)sorted(by:) con una comparación mediante ruta de claves
Para ordenar por una propiedad, todavía debe escribir un pequeño closure de comparación, pero puede leer la propiedad mediante una ruta de claves dentro de él para mayor claridad.
Aquí ordenamos a las personas de menor a mayor edad comparando sus valores de age.
struct Person {
let name: String
let age: Int
}
let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
let path = \Person.age
let sorted = people.sorted { $0[keyPath: path] < $1[keyPath: path] }
print(sorted.map(\.name))Un helper de ordenación reutilizable
Puede escribir un helper genérico que ordene cualquier array por cualquier propiedad comparable, tomando la propiedad como argumento de ruta de claves. Así, ordenar por un campo se convierte en una sola línea en todo el código base.
La restricción T: Comparable garantiza que la propiedad se pueda ordenar.
func sorted<E, T: Comparable>(_ array: [E], by path: KeyPath<E, T>) -> [E] {
array.sorted { $0[keyPath: path] < $1[keyPath: path] }
}
struct Person { let name: String; let age: Int }
let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
print(sorted(people, by: \.age).map(\.name))Filtrar mediante una ruta de claves
Para filter necesita un predicado que devuelva un Bool, por lo que una ruta de claves de propiedad independiente solo funciona directamente cuando la propiedad ya es un Bool.
Aquí cada tarea tiene un indicador isDone, y filtramos usando la notación abreviada de ruta de claves.
struct Task {
let title: String
let isDone: Bool
}
let tasks = [Task(title: "A", isDone: true), Task(title: "B", isDone: false)]
let finished = tasks.filter(\.isDone)
print(finished.map(\.title))Filtrar por una propiedad que no es Bool
Cuando filtra por una propiedad que no es Bool, léala mediante una ruta de claves dentro de un closure y compárela. Un helper genérico puede encapsular este patrón para cualquier propiedad equatable.
Aquí conservamos solo a las personas cuya ciudad coincide con un destino.
struct Person { let name: String; let city: String }
func filter<E, T: Equatable>(_ array: [E], _ path: KeyPath<E, T>, equals value: T) -> [E] {
array.filter { $0[keyPath: path] == value }
}
let people = [Person(name: "Ana", city: "Oslo"), Person(name: "Ben", city: "Rome")]
print(filter(people, \.city, equals: "Oslo").map(\.name))max y min mediante una ruta de claves
Los métodos max(by:) y min(by:) reciben un closure de comparación, igual que sorted. Lea la propiedad mediante una ruta de claves para encontrar el elemento con el valor mayor o menor.
Aquí encontramos a la persona de mayor edad.
struct Person { let name: String; let age: Int }
let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25), Person(name: "Cy", age: 41)]
let path = \Person.age
if let oldest = people.max(by: { $0[keyPath: path] < $1[keyPath: path] }) {
print(oldest.name)
}Sumar una propiedad con reduce
Puede combinar map(\.property) con reduce para totalizar un campo numérico. Primero proyecte cada elemento al número que desea y después súmelos.
Aquí sumamos todas las edades en un solo pipeline.
struct Person { let name: String; let age: Int }
let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
let totalAge = people.map(\.age).reduce(0, +)
print(totalAge)Agrupar mediante una ruta de claves
Dictionary(grouping:by:) agrupa los elementos según el resultado de un closure. Lea una propiedad mediante una ruta de claves para agrupar por ese campo.
Aquí agrupamos a las personas por ciudad en un diccionario de arrays.
struct Person { let name: String; let city: String }
let people = [
Person(name: "Ana", city: "Oslo"),
Person(name: "Ben", city: "Rome"),
Person(name: "Cy", city: "Oslo")
]
let path = \Person.city
let byCity = Dictionary(grouping: people, by: { $0[keyPath: path] })
print(byCity["Oslo"]?.map(\.name) ?? [])Ordenación por varios campos
Para ordenar por un campo y resolver los empates con otro, compare primero la ruta de claves principal y, cuando los valores principales sean iguales, recurra a la secundaria.
Aquí ordenamos por edad y después por nombre cuando las edades coinciden.
struct Person { let name: String; let age: Int }
let people = [
Person(name: "Zoe", age: 30),
Person(name: "Ana", age: 30),
Person(name: "Ben", age: 25)
]
let sorted = people.sorted {
if $0[keyPath: \Person.age] != $1[keyPath: \Person.age] {
return $0.age < $1.age
}
return $0.name < $1.name
}
print(sorted.map(\.name))Por qué aquí las rutas de claves superan a los closures
Usar rutas de claves en las llamadas a colecciones reduce el código repetitivo, elimina la posibilidad de escribir mal algo en el cuerpo del closure y deja clara la intención: proyectar un solo campo.
Para transformaciones complejas, un closure sigue siendo la herramienta adecuada, pero para una simple lectura de propiedad, \.property es la opción más clara.
struct Product { let name: String; let price: Double }
let products = [Product(name: "Pen", price: 2), Product(name: "Pad", price: 5)]
let names = products.map(\.name)
let prices = products.map(\.price)
print(names)
print(prices)Comprobación rápida: ruta de claves en map
Elija la forma concisa con ruta de claves para extraer una propiedad de cada elemento.
Resumen: rutas de claves en colecciones
Ha visto cómo las rutas de claves permiten escribir código conciso para colecciones:
map(\.property)proyecta un solo campo sin un closure.filter(\.boolProperty)funciona directamente con campos Bool; para los demás, use un closure con[keyPath:].- La ordenación,
maxyminleen la propiedad mediante una ruta de claves dentro de sus closures de comparación. - Los helpers genéricos que reciben un
KeyPathconvierten la ordenación y el filtrado por un campo en operaciones reutilizables de una sola línea.
A continuación aprenderá sobre las rutas de claves modificables, que permiten establecer valores, no solo leerlos.
struct Person { let name: String; let age: Int }
let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
let youngestFirst = people.sorted { $0[keyPath: \Person.age] < $1[keyPath: \Person.age] }
print(youngestFirst.map(\.name))Aprende Swift con un tutor de IA — gratis
Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.
- Cursos
- 122
- Lecciones
- 409
Preguntas frecuentes
¿La lección «Uso de KeyPaths en colecciones» es gratis?
Sí — el texto completo de «Uso de KeyPaths en colecciones» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Swift Academy, actualiza a CoddyKit PRO. El curso de Swift Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Uso de KeyPaths en colecciones»?
Ordene y transforme colecciones mediante rutas de claves. Practicas Swift Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Swift Academy?
No se requiere experiencia previa. Swift Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.
¿Cuánto tiempo toma la lección «Uso de KeyPaths en colecciones»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Swift Academy?
Sí. Cada lección de Swift Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Fundamentos de KeyPath
- Uso de KeyPaths en colecciones
- KeyPaths modificables y de referencia
- @dynamicMemberLookup