Haz todo lo posible por entender el código correctamente antes de utilizarlo a tu trabajo y si tquieres aportar algo puedes compartirlo con nosotros.
Solución:
Rápido 4:
Desde Swift 4, esta funcionalidad se ha agregado a la biblioteca estándar. Puedes usarlo así:
Dictionary(grouping: statEvents, by: $0.name )
[
"dinner": [
StatEvents(name: "dinner", date: "01-01-2015", hours: 1),
StatEvents(name: "dinner", date: "01-01-2015", hours: 1),
StatEvents(name: "dinner", date: "01-01-2015", hours: 1)
],
"lunch": [
StatEvents(name: "lunch", date: "01-01-2015", hours: 1),
StatEvents(name: "lunch", date: "01-01-2015", hours: 1)
]
Rápido 3:
public extension Sequence
func group(by key: (Iterator.Element) -> U) -> [U:[Iterator.Element]]
var categories: [U: [Iterator.Element]] = [:]
for element in self
let key = key(element)
if case nil = categories[key]?.append(element)
categories[key] = [element]
return categories
Desafortunadamente, el append
la función anterior copia el subyacente array, en lugar de mutarlo en su lugar, lo que sería preferible. Esto provoca una desaceleración bastante grande. Puede solucionar el problema utilizando un contenedor de tipo de referencia:
class Box
var value: A
init(_ val: A)
self.value = val
public extension Sequence
func group(by key: (Iterator.Element) -> U) -> [U:[Iterator.Element]]
var categories: [U: Box<[Iterator.Element]>] = [:]
for element in self
let key = key(element)
if case nil = categories[key]?.value.append(element)
categories[key] = Box([element])
var result: [U: [Iterator.Element]] = Dictionary(minimumCapacity: categories.count)
for (key,val) in categories
result[key] = val.value
return result
Aunque recorra el diccionario final dos veces, esta versión sigue siendo más rápida que la original en la mayoría de los casos.
Rápido 2:
public extension SequenceType
/// Categorises elements of self into a dictionary, with the keys given by keyFunc
func categorise(@noescape keyFunc: Generator.Element -> U) -> [U:[Generator.Element]]
var dict: [U:[Generator.Element]] = [:]
for el in self
let key = keyFunc(el)
if case nil = dict[key]?.append(el) dict[key] = [el]
return dict
En su caso, podría tener el “keys”devuelto por keyFunc
sean los nombres:
currentStat.statEvents.categorise $0.name
[
dinner: [
StatEvents(name: "dinner", date: "01-01-2015", hours: 1),
StatEvents(name: "dinner", date: "01-01-2015", hours: 1),
StatEvents(name: "dinner", date: "01-01-2015", hours: 1)
], lunch: [
StatEvents(name: "lunch", date: "01-01-2015", hours: 1),
StatEvents(name: "lunch", date: "01-01-2015", hours: 1)
]
]
Entonces obtendrá un diccionario, donde cada key es un nombre, y cada valor es un array de StatEvents con ese nombre.
Rápido 1
func categorise(seq: S, @noescape keyFunc: S.Generator.Element -> U) -> [U:[S.Generator.Element]]
var dict: [U:[S.Generator.Element]] = [:]
for el in seq
let key = keyFunc(el)
dict[key] = (dict[key] ?? []) + [el]
return dict
categorise(currentStat.statEvents) $0.name
Lo que da la salida:
extension StatEvents : Printable
var description: String
return "(self.name): (self.date)"
print(categorise(currentStat.statEvents) $0.name )
[
dinner: [
dinner: 01-01-2015,
dinner: 01-01-2015,
dinner: 01-01-2015
], lunch: [
lunch: 01-01-2015,
lunch: 01-01-2015
]
]
(El Swiftstub está aquí)
Con Swift 5, Dictionary
tiene un método de inicialización llamado init(grouping:by:)
. init(grouping:by:)
tiene la siguiente declaración:
init(grouping values: S, by keyForValue: (S.Element) throws -> Key) rethrows where Value == [S.Element], S : Sequence
Crea un nuevo diccionario donde el keys son las agrupaciones devueltas por el cierre dado y los valores son matrices de los elementos que devolvieron cada específico key.
El siguiente código de Playground muestra cómo usar init(grouping:by:)
para solucionar su problema:
struct StatEvents: CustomStringConvertible
let name: String
let date: String
let hours: Int
var description: String
return "Event: (name) - (date) - (hours)"
let statEvents = [
StatEvents(name: "lunch", date: "01-01-2015", hours: 1),
StatEvents(name: "dinner", date: "01-01-2015", hours: 1),
StatEvents(name: "lunch", date: "01-01-2015", hours: 1),
StatEvents(name: "dinner", date: "01-01-2015", hours: 1)
]
let dictionary = Dictionary(grouping: statEvents, by: (element: StatEvents) in
return element.name
)
//let dictionary = Dictionary(grouping: statEvents) $0.name // also works
//let dictionary = Dictionary(grouping: statEvents, by: .name) // also works
print(dictionary)
/*
prints:
[
"dinner": [Event: dinner - 01-01-2015 - 1, Event: dinner - 01-01-2015 - 1],
"lunch": [Event: lunch - 01-01-2015 - 1, Event: lunch - 01-01-2015 - 1]
]
*/
Swift 4: puedes usar init (agrupación: por 🙂 desde el sitio de desarrolladores de Apple
Ejemplo:
let students = ["Kofi", "Abena", "Efua", "Kweku", "Akosua"]
let studentsByLetter = Dictionary(grouping: students, by: $0.first! )
// ["E": ["Efua"], "K": ["Kofi", "Kweku"], "A": ["Abena", "Akosua"]]
Entonces en tu caso
let dictionary = Dictionary(grouping: currentStat.statEvents, by: $0.name! )
Sección de Reseñas y Valoraciones
Si haces scroll puedes encontrar las ilustraciones de otros desarrolladores, tú además tienes la opción de insertar el tuyo si lo crees conveniente.