resueltos metodos lista elementos ejercicios diccionarios diccionario dentro convertir anidados agregar dictionary swift

dictionary - metodos - lista dentro de un diccionario python



Cómo se agrega un Diccionario de elementos a otro Diccionario (24)

Las matrices en Swift admiten el operador + = para agregar el contenido de una matriz a otra. ¿Hay alguna manera fácil de hacer eso para un diccionario?

p.ej:

var dict1 = ["a" : "foo"] var dict2 = ["b" : "bar"] var combinedDict = ... (some way of combining dict1 & dict2 without looping)


Inmutable

Prefiero combinar / unir diccionarios inmutables con el operador + , así que lo implementé como:

// Swift 2 func + <K,V> (left: Dictionary<K,V>, right: Dictionary<K,V>?) -> Dictionary<K,V> { guard let right = right else { return left } return left.reduce(right) { var new = $0 as [K:V] new.updateValue($1.1, forKey: $1.0) return new } } let moreAttributes: [String:AnyObject] = ["Function":"authenticate"] let attributes: [String:AnyObject] = ["File":"Auth.swift"] attributes + moreAttributes + nil //["Function": "authenticate", "File": "Auth.swift"] attributes + moreAttributes //["Function": "authenticate", "File": "Auth.swift"] attributes + nil //["File": "Auth.swift"]

Mudable

// Swift 2 func += <K,V> (inout left: Dictionary<K,V>, right: Dictionary<K,V>?) { guard let right = right else { return } right.forEach { key, value in left.updateValue(value, forKey: key) } } let moreAttributes: [String:AnyObject] = ["Function":"authenticate"] var attributes: [String:AnyObject] = ["File":"Auth.swift"] attributes += nil //["File": "Auth.swift"] attributes += moreAttributes //["File": "Auth.swift", "Function": "authenticate"]


Actualmente, al mirar la Referencia de la Biblioteca Estándar de Swift para el Diccionario, no hay forma de actualizar fácilmente un diccionario con otro.

Puedes escribir una extensión para hacerlo

var dict1 = ["a" : "foo"] var dict2 = ["b" : "bar"] extension Dictionary { mutating func update(other:Dictionary) { for (key,value) in other { self.updateValue(value, forKey:key) } } } dict1.update(dict2) // dict1 is now ["a" : "foo", "b" : "bar]


En Swift 4, uno debería usar merging(_:uniquingKeysWith:) :

Ejemplo:

let dictA = ["x" : 1, "y": 2, "z": 3] let dictB = ["x" : 11, "y": 22, "w": 0] let resultA = dictA.merging(dictB, uniquingKeysWith: { (first, _) in first }) let resultB = dictA.merging(dictB, uniquingKeysWith: { (_, last) in last }) print(resultA) // ["x": 1, "y": 2, "z": 3, "w": 0] print(resultB) // ["x": 11, "y": 22, "z": 3, "w": 0]


La biblioteca ExSwift proporciona fusión de diccionarios (llamada Unión, y se define como el operador de tubería ''|''), así como una tonelada de otras funciones de conveniencia para los tipos básicos.


Lo mismo que la respuesta de @ farhadf pero adoptada para Swift 3:

let sourceDict1 = [1: "one", 2: "two"] let sourceDict2 = [3: "three", 4: "four"] let result = sourceDict1.reduce(sourceDict2) { (partialResult , pair) in var partialResult = partialResult //without this line we could not modify the dictionary partialResult[pair.0] = pair.1 return partialResult }


Mis necesidades eran diferentes, necesitaba fusionar conjuntos de datos anidados incompletos sin tropezar.

merging: ["b": [1, 2], "s": Set([5, 6]), "a": 1, "d": ["x": 2]] with ["b": [3, 4], "s": Set([6, 7]), "a": 2, "d": ["y": 4]] yields: ["b": [1, 2, 3, 4], "s": Set([5, 6, 7]), "a": 2, "d": ["y": 4, "x": 2]]

Esto fue más difícil de lo que yo quería. El desafío estaba en el mapeo de la tipificación dinámica a la tipificación estática, y utilicé protocolos para resolver esto.

También es digno de mención que cuando utiliza la sintaxis literal de diccionario, realmente obtiene los tipos de fundación, que no recogen las extensiones de protocolo. He abortado mis esfuerzos para apoyar a los que no pude encontrar una manera fácil de validar la uniformidad de los elementos de la colección.

import UIKit private protocol Mergable { func mergeWithSame<T>(right: T) -> T? } public extension Dictionary { /** Merge Dictionaries - Parameter left: Dictionary to update - Parameter right: Source dictionary with values to be merged - Returns: Merged dictionay */ func merge(right:Dictionary) -> Dictionary { var merged = self for (k, rv) in right { // case of existing left value if let lv = self[k] { if let lv = lv as? Mergable where lv.dynamicType == rv.dynamicType { let m = lv.mergeWithSame(rv) merged[k] = m } else if lv is Mergable { assert(false, "Expected common type for matching keys!") } else if !(lv is Mergable), let _ = lv as? NSArray { assert(false, "Dictionary literals use incompatible Foundation Types") } else if !(lv is Mergable), let _ = lv as? NSDictionary { assert(false, "Dictionary literals use incompatible Foundation Types") } else { merged[k] = rv } } // case of no existing value else { merged[k] = rv } } return merged } } extension Array: Mergable { func mergeWithSame<T>(right: T) -> T? { if let right = right as? Array { return (self + right) as? T } assert(false) return nil } } extension Dictionary: Mergable { func mergeWithSame<T>(right: T) -> T? { if let right = right as? Dictionary { return self.merge(right) as? T } assert(false) return nil } } extension Set: Mergable { func mergeWithSame<T>(right: T) -> T? { if let right = right as? Set { return self.union(right) as? T } assert(false) return nil } } var dsa12 = Dictionary<String, Any>() dsa12["a"] = 1 dsa12["b"] = [1, 2] dsa12["s"] = Set([5, 6]) dsa12["d"] = ["c":5, "x": 2] var dsa34 = Dictionary<String, Any>() dsa34["a"] = 2 dsa34["b"] = [3, 4] dsa34["s"] = Set([6, 7]) dsa34["d"] = ["c":-5, "y": 4] //let dsa2 = ["a": 1, "b":a34] let mdsa3 = dsa12.merge(dsa34) print("merging:/n/t/(dsa12)/nwith/n/t/(dsa34) /nyields: /n/t/(mdsa3)")


No es necesario tener extensiones de diccionario ahora. El diccionario Swift (Xcode 9.0+) tiene una funcionalidad para esto. Echa un vistazo here . A continuación hay un ejemplo sobre cómo usarlo

var oldDictionary = ["a": 1, "b": 2] var newDictionary = ["a": 10000, "b": 10000, "c": 4] oldDictionary.merge(newDictionary) { (oldValue, newValue) -> Int in // This closure return what value to consider if repeated keys are found return newValue } print(oldDictionary) // Prints ["b": 10000, "a": 10000, "c": 4]


No está integrado en la biblioteca de Swift, pero puede agregar lo que desee con la sobrecarga del operador, por ejemplo:

func + <K,V>(left: Dictionary<K,V>, right: Dictionary<K,V>) -> Dictionary<K,V> { var map = Dictionary<K,V>() for (k, v) in left { map[k] = v } for (k, v) in right { map[k] = v } return map }

Esto sobrecarga el operador + para diccionarios que ahora puede usar para agregar diccionarios con el operador + , por ejemplo:

var dict1 = ["a" : "foo"] var dict2 = ["b" : "bar"] var dict3 = dict1 + dict2 // ["a": "foo", "b": "bar"]


Puede agregar una extensión de Dictionary como esta:

extension Dictionary { func mergedWith(otherDictionary: [Key: Value]) -> [Key: Value] { var mergedDict: [Key: Value] = [:] [self, otherDictionary].forEach { dict in for (key, value) in dict { mergedDict[key] = value } } return mergedDict } }

Entonces el uso es tan simple como lo siguiente:

var dict1 = ["a" : "foo"] var dict2 = ["b" : "bar"] var combinedDict = dict1.mergedWith(dict2) // => ["a": "foo", "b": "bar"]

Si prefiere un marco que también incluya algunas funciones más prácticas, HandySwift compra de HandySwift . Simplemente importe a su proyecto y puede usar el código anterior sin agregar ninguna extensión al proyecto usted mismo.


Puede definir += operator para Dictionary , por ejemplo,

func += <K, V> (left: inout [K:V], right: [K:V]) { for (k, v) in right { left[k] = v } }


Puede iterar sobre las combinaciones de valores clave ob el valor que desea fusionar y agregarlos a través del método updateValue (forKey :):

dictionaryTwo.forEach { dictionaryOne.updateValue($1, forKey: $0) }

Ahora todos los valores de dictionaryTwo se agregaron a dictionaryOne.


Puede usar la función bridgeToObjectiveC () para hacer que el diccionario sea un NSDictionary.

Será como el siguiente:

var dict1 = ["a":"Foo"] var dict2 = ["b":"Boo"] var combinedDict = dict1.bridgeToObjectiveC() var mutiDict1 : NSMutableDictionary! = combinedDict.mutableCopy() as NSMutableDictionary var combineDict2 = dict2.bridgeToObjectiveC() var combine = mutiDict1.addEntriesFromDictionary(combineDict2)

Luego puede convertir el NSDictionary (combinar) de nuevo o hacer lo que sea.


Puedes intentar esto

var dict1 = ["a" : "foo"] var dict2 = ["b" : "bar"] var temp = NSMutableDictionary(dictionary: dict1); temp .addEntriesFromDictionary(dict2)


Qué tal si

dict2.forEach { (k,v) in dict1[k] = v }

Eso agrega todas las claves y valores de dict2 a dict1.


Recomiendo la Biblioteca SwifterSwift . Sin embargo, si no desea utilizar toda la biblioteca y todas sus grandes adiciones, puede hacer uso de su extensión de Diccionario:

Swift 3+

public extension Dictionary { public static func +=(lhs: inout [Key: Value], rhs: [Key: Value]) { rhs.forEach({ lhs[$0] = $1}) } }


Solo usaría la biblioteca de Dollar .

https://github.com/ankurp/Dollar/#merge---merge-1

Fusiona todos los diccionarios y el último diccionario anula el valor en una tecla determinada

let dict: Dictionary<String, Int> = ["Dog": 1, "Cat": 2] let dict2: Dictionary<String, Int> = ["Cow": 3] let dict3: Dictionary<String, Int> = ["Sheep": 4] $.merge(dict, dict2, dict3) => ["Dog": 1, "Cat": 2, "Cow": 3, "Sheep": 4]


Swift 2.0

extension Dictionary { mutating func unionInPlace(dictionary: Dictionary) { dictionary.forEach { self.updateValue($1, forKey: $0) } } func union(var dictionary: Dictionary) -> Dictionary { dictionary.unionInPlace(self) return dictionary } }


Swift 2.2

func + <K,V>(left: [K : V], right: [K : V]) -> [K : V] { var result = [K:V]() for (key,value) in left { result[key] = value } for (key,value) in right { result[key] = value } return result }


Swift 3, extensión del diccionario:

public extension Dictionary { public static func +=(lhs: inout Dictionary, rhs: Dictionary) { for (k, v) in rhs { lhs[k] = v } } }


Swift 3:

extension Dictionary { mutating func merge(with dictionary: Dictionary) { dictionary.forEach { updateValue($1, forKey: $0) } } func merged(with dictionary: Dictionary) -> Dictionary { var dict = self dict.merge(with: dictionary) return dict } } let a = ["a":"b"] let b = ["1":"2"] let c = a.merged(with: b) print(c) //["a": "b", "1": "2"]


También puede usar reducir para fusionarlos. Prueba esto en el patio de recreo

let d1 = ["a":"foo","b":"bar"] let d2 = ["c":"car","d":"door"] let d3 = d1.reduce(d2) { (var d, p) in d[p.0] = p.1 return d }


Todas estas respuestas son complicadas. Esta es mi solución para quick 2.2:

//get first dictionnary let finalDictionnary : NSMutableDictionary = self.getBasicDict() //cast second dictionnary as [NSObject : AnyObject] let secondDictionnary : [NSObject : AnyObject] = self.getOtherDict() as [NSObject : AnyObject] //merge dictionnary into the first one finalDictionnary.addEntriesFromDictionary(secondDictionnary)


Una variante más legible usando una extensión.

extension Dictionary { func merge(dict: Dictionary<Key,Value>) -> Dictionary<Key,Value> { var mutableCopy = self for (key, value) in dict { // If both dictionaries have a value for same key, the value of the other dictionary is used. mutableCopy[key] = value } return mutableCopy } }


import Foundation let x = ["a":1] let y = ["b":2] let out = NSMutableDictionary(dictionary: x) out.addEntriesFromDictionary(y)

El resultado es un NSMutableDictionary, no un diccionario de tipo Swift, pero la sintaxis para usar es la misma ( out["a"] == 1 en este caso) por lo que solo tendrías un problema si estás usando un tercero. código que espera un diccionario Swift, o realmente necesita la verificación de tipo.

La respuesta corta aquí es que realmente tiene que hacer un bucle. Incluso si no lo está ingresando explícitamente, eso es lo que hará el método que está llamando (addEntriesFromDictionary: here). Sugeriría que si no está claro por qué sería ese el caso, debería considerar cómo fusionaría los nodos de las hojas de dos árboles B.

Si realmente necesita un tipo de diccionario nativo Swift a cambio, le sugiero:

let x = ["a":1] let y = ["b":2] var out = x for (k, v) in y { out[k] = v }

La desventaja de este enfoque es que el índice del diccionario, como sea que esté hecho, puede reconstruirse varias veces en el ciclo, por lo que en la práctica es 10 veces más lento que el método NSMutableDictionary.