write tutorial read arrays swift dictionary filter

arrays - tutorial - read fasta python



Swift 3: Array to Dictionary? (8)

Tengo una gran variedad y necesito acceder a ella mediante una clave (una búsqueda), así que necesito crear el Diccionario. ¿Hay una función incorporada en Swift 3.0 para hacerlo, o tengo que escribirla yo mismo?

Primero lo necesitaré para una clase con la tecla "Cadena" y luego tal vez pueda escribir una versión de plantilla para fines generales (todo tipo de datos y clave).


¿Es eso (en Swift 4)?

let dict = Dictionary(uniqueKeysWithValues: array.map{ ($0.key, $0) })


Como entiendo de su pregunta, le gustaría convertir a Array to Dictionary .

En mi caso, creo una extension para el Array y las claves para el diccionario serán los índices del Array .

Ejemplo:

var intArray = [2, 3, 5, 3, 2, 1] extension Array where Element: Any { var toDictionary: [Int:Element] { var dictionary: [Int:Element] = [:] for (index, element) in enumerate() { dictionary[index] = element } return dictionary } } let dic = intArray.toDictionary


Como ya han dicho otros, tenemos que entender cuáles son las claves.

Sin embargo, estoy tratando de proporcionar una solución a mi interpretación de su pregunta.

struct User { let id: String let firstName: String let lastName: String }

Aquí asumo que no pueden existir 2 usuarios con el mismo id

let users: [User] = ... let dict = users.reduce([String:User]()) { (result, user) -> [String:User] in var result = result result[user.id] = user return result }

Ahora dict es un diccionario donde la key es la user id del user id y el value es el user value .

Para acceder a un usuario a través de su id , ahora puede simplemente escribir

let user = dict["123"]

Actualización # 1: enfoque general

Dada una matriz de un Element tipo dado y un cierre que determina la key de un Element , la siguiente función genérica generará un Dictionary de tipo [Key:Element]

func createIndex<Key, Element>(elms:[Element], extractKey:(Element) -> Key) -> [Key:Element] where Key : Hashable { return elms.reduce([Key:Element]()) { (dict, elm) -> [Key:Element] in var dict = dict dict[extractKey(elm)] = elm return dict } }

Ejemplo

let users: [User] = [ User(id: "a0", firstName: "a1", lastName: "a2"), User(id: "b0", firstName: "b1", lastName: "b2"), User(id: "c0", firstName: "c1", lastName: "c2") ] let dict = createIndex(elms: users) { $0.id } // ["b0": {id "b0", firstName "b1", lastName "b2"}, "c0": {id "c0", firstName "c1", lastName "c2"}, "a0": {id "a0", firstName "a1", lastName "a2"}]

Actualización # 2

Como señaló Martin R, la reducción creará un nuevo diccionario para cada iteración del cierre relacionado. Esto podría llevar a un gran consumo de memoria.

Aquí hay otra versión de la función createIndex donde el requisito de espacio es O (n) donde n es la longitud de los olmos.

func createIndex<Key, Element>(elms:[Element], extractKey:(Element) -> Key) -> [Key:Element] where Key : Hashable { var dict = [Key:Element]() for elm in elms { dict[extractKey(elm)] = elm } return dict }


Creo que estás buscando algo como esto:

extension Array { public func toDictionary<Key: Hashable>(with selectKey: (Element) -> Key) -> [Key:Element] { var dict = [Key:Element]() for element in self { dict[selectKey(element)] = element } return dict } }

Ahora puedes hacer:

struct Person { var name: String var surname: String var identifier: String } let arr = [Person(name: "John", surname: "Doe", identifier: "JOD"), Person(name: "Jane", surname: "Doe", identifier: "JAD")] let dict = arr.toDictionary { $0.identifier } print(dict) // Result: ["JAD": Person(name: "Jane", surname: "Doe", identifier: "JAD"), "JOD": Person(name: "John", surname: "Doe", identifier: "JOD")]

Si desea que su código sea más general, incluso podría agregar esta extensión en Sequence lugar de Array :

extension Sequence { public func toDictionary<Key: Hashable>(with selectKey: (Iterator.Element) -> Key) -> [Key:Iterator.Element] { var dict: [Key:Iterator.Element] = [:] for element in self { dict[selectKey(element)] = element } return dict } }

Tenga en cuenta que esto hace que la secuencia se repita y en algunos casos podría tener efectos secundarios.


En Swift 4, puede lograr esto utilizando la grouping:by: del Diccionario grouping:by: inicializador

Por ejemplo: tienes clase llamada A

class A { var name: String init(name: String) { self.name = name } // . // . // . // other declations and implementions }

A continuación, tienes una matriz de objetos de tipo A

let a1 = A(name: "Joy") let a2 = A(name: "Ben") let a3 = A(name: "Boy") let a4 = A(name: "Toy") let a5 = A(name: "Tim") let array = [a1, a2, a3, a4, a5]

Supongamos que desea crear un Diccionario agrupando todos los nombres por su primera letra. Utiliza Swifts Dictionary(grouping:by:) para lograr esto

let dictionary = Dictionary(grouping: array, by: { $0.name.first! }) // this will give you a dictionary // ["J": [a1], "B": [a2, a3], "T": [a4, a5]]

source


Esta extensión funciona para todas las secuencias (incluidas las matrices) y le permite seleccionar tanto la clave como el valor :

extension Sequence { public func toDictionary<K: Hashable, V>(_ selector: (Iterator.Element) throws -> (K, V)?) rethrows -> [K: V] { var dict = [K: V]() for element in self { if let (key, value) = try selector(element) { dict[key] = value } } return dict } }

Ejemplo:

let nameLookup = persons.toDictionary{($0.name, $0)}


Lo siguiente convierte una matriz en un diccionario.

let firstArray = [2,3,4,5,5] let dict = Dictionary(firstArray.map { ($0, 1) } , uniquingKeysWith: +)


Sólo hazlo simplemente,

let items = URLComponents(string: "https://im.qq.com?q=13&id=23")!.queryItems! var dic = [String: Any?]() items.foreach { dic[$0.name] = $0.value }

reduce no es muy adecuado,

let dic: [String: Any?] = items.reduce([:]) { (result: [String: Any?], item: URLQueryItem) -> [String: Any?] in var r = result r[item.name] = item.value // will create an copy of result!!!!!! return r }