다른 사전에 항목 사전을 추가하는 방법
Swift의 배열은 + = 연산자를 지원하여 한 배열의 내용을 다른 배열에 추가합니다. 사전을 위해 쉬운 방법이 있습니까?
예 :
var dict1 = ["a" : "foo"]
var dict2 = ["b" : "bar"]
var combinedDict = ... (some way of combining dict1 & dict2 without looping)
에 +=
대한 연산자를 정의 할 수 있습니다 ( Dictionary
예 :
func += <K, V> (left: inout [K:V], right: [K:V]) {
for (k, v) in right {
left[k] = v
}
}
어때요?
dict2.forEach { (k,v) in dict1[k] = v }
dict2의 모든 키와 값이 dict1에 추가됩니다.
Swift 4에서는 다음을 사용해야합니다 merging(_:uniquingKeysWith:)
.
예:
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]
현재 Swift Standard Library Reference for Dictionary를 보면 사전을 다른 사전으로 쉽게 업데이트 할 수있는 방법이 없습니다.
당신은 그것을 할 확장을 쓸 수 있습니다
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]
Swift 4 는 merging(_:uniquingKeysWith:)
귀하의 경우에 다음을 제공합니다 .
let combinedDict = dict1.merging(dict2) { $1 }
속기 클로저는을 반환 $1
하므로 키와 충돌이있을 때 dict2의 값이 사용됩니다.
Swift 라이브러리에 내장되어 있지 않지만 연산자 오버로드로 원하는 것을 추가 할 수 있습니다. 예 :
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
}
이렇게하면 +
연산자에 사전을 추가하는 데 사용할 수있는 사전에 대한 연산자가 오버로드됩니다. +
예 :
var dict1 = ["a" : "foo"]
var dict2 = ["b" : "bar"]
var dict3 = dict1 + dict2 // ["a": "foo", "b": "bar"]
스위프트 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"]
스위프트 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
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"]
변하기 쉬운
// 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"]
사전 확장이 필요 없습니다. Swift (Xcode 9.0+) 사전에는이 기능이 있습니다. 봐 가지고 여기를 . 아래는 사용 방법에 대한 예입니다.
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]
당신은 이것을 시도 할 수 있습니다
var dict1 = ["a" : "foo"]
var dict2 = ["b" : "bar"]
var temp = NSMutableDictionary(dictionary: dict1);
temp.addEntriesFromDictionary(dict2)
확장을 사용하는 더 읽기 쉬운 변형.
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
}
}
reduce를 사용하여 병합 할 수도 있습니다. 운동장에서 이것을 시도하십시오
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
}
SwifterSwift Library를 권장합니다 . 그러나 전체 라이브러리와 모든 추가 기능을 사용하지 않으려는 경우 사전 확장을 사용할 수 있습니다.
스위프트 3+
public extension Dictionary {
public static func +=(lhs: inout [Key: Value], rhs: [Key: Value]) {
rhs.forEach({ lhs[$0] = $1})
}
}
updateValue (forKey :) 메소드를 통해 병합하려는 값과 키 값 조합을 반복하여 추가 할 수 있습니다.
dictionaryTwo.forEach {
dictionaryOne.updateValue($1, forKey: $0)
}
이제 dictionaryTwo의 모든 값이 dictionaryOne에 추가되었습니다.
@farhadf의 답변과 동일하지만 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
}
스위프트 3, 사전 확장 :
public extension Dictionary {
public static func +=(lhs: inout Dictionary, rhs: Dictionary) {
for (k, v) in rhs {
lhs[k] = v
}
}
}
다음 과 같이 Dictionary
확장명을 추가 할 수 있습니다 .
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
}
}
그런 다음 사용법 은 다음과 같이 간단 합니다.
var dict1 = ["a" : "foo"]
var dict2 = ["b" : "bar"]
var combinedDict = dict1.mergedWith(dict2)
// => ["a": "foo", "b": "bar"]
좀 더 편리한 기능 을 포함하는 프레임 워크를 선호한다면 HandySwift 를 확인 하십시오 . 그냥 프로젝트로 가져올 당신은 위의 코드를 사용할 수 있는 확장 기능을 추가하지 않고 프로젝트를 자신에게.
Swift 4의 경우 더욱 간소화 된 과부하가 발생합니다.
extension Dictionary {
static func += (lhs: inout [Key:Value], rhs: [Key:Value]) {
lhs.merge(rhs){$1}
}
static func + (lhs: [Key:Value], rhs: [Key:Value]) -> [Key:Value] {
return lhs.merging(rhs){$1}
}
}
더 이상 확장이나 추가 기능이 필요하지 않습니다. 당신은 그렇게 쓸 수 있습니다 :
firstDictionary.merge(secondDictionary) { (value1, value2) -> AnyObject in
return object2 // what you want to return if keys same.
}
bridgeToObjectiveC () 함수를 사용하여 사전을 NSDictionary로 만들 수 있습니다.
다음과 같습니다.
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)
그런 다음 NSDictionary (combine)를 다시 변환하거나 무엇이든 할 수 있습니다.
import Foundation
let x = ["a":1]
let y = ["b":2]
let out = NSMutableDictionary(dictionary: x)
out.addEntriesFromDictionary(y)
결과는 Swift 유형 사전이 아닌 NSMutableDictionary이지만이 구문을 사용하는 구문은 동일 out["a"] == 1
하므로 ( 이 경우) Swift 사전을 기대하는 타사 코드를 사용하는 경우에만 문제가 발생합니다. 유형 검사가 필요합니다.
여기서 짧은 대답은 실제로 반복해야한다는 것입니다. 명시 적으로 입력하지 않더라도 호출하는 메소드 (addEntriesFromDictionary : here)가 수행하는 방식입니다. 왜 그런지 잘 모르겠다면 두 개의 B-tree의 리프 노드를 병합하는 방법을 고려해야합니다.
실제로 Swift 기본 사전 유형이 실제로 필요한 경우 다음을 제안합니다.
let x = ["a":1]
let y = ["b":2]
var out = x
for (k, v) in y {
out[k] = v
}
이 방법의 단점은 루프에서 사전 색인이 여러 번 재 빌드 될 수 있으므로 실제로 NSMutableDictionary 방식보다 약 10 배 느리다는 것입니다.
이 모든 응답은 복잡합니다. 이것은 신속한 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)
내 요구는 달랐으며, 클로버 링없이 불완전한 중첩 데이터 세트를 병합해야했습니다.
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]]
이것은 내가 원했던 것보다 더 힘들었습니다. 문제는 동적 타이핑에서 정적 타이핑으로 매핑하는 것이 었으며,이를 해결하기 위해 프로토콜을 사용했습니다.
또한 사전 리터럴 구문을 사용할 때 실제로 프로토콜 확장을 선택하지 않는 기본 유형을 얻습니다. 수집 요소의 균일 성을 검증하기가 쉽지 않기 때문에이를 지원하려는 노력을 중단했습니다.
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)")
스위프트 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
}
I would just use the Dollar library.
https://github.com/ankurp/Dollar/#merge---merge-1
Merges all of the dictionaries together and the latter dictionary overrides the value at a given key
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]
Here is a nice extension I wrote...
extension Dictionary where Value: Any {
public func mergeOnto(target: [Key: Value]?) -> [Key: Value] {
guard let target = target else { return self }
return self.merging(target) { current, _ in current }
}
}
to use:
var dict1 = ["cat": 5, "dog": 6]
var dict2 = ["dog": 9, "rodent": 10]
dict1 = dict1.mergeOnto(target: dict2)
Then, dict1 will be modified to
["cat": 5, "dog": 6, "rodent": 10]
'IT story' 카테고리의 다른 글
배경색과 관련된 CSS @media 인쇄 문제; (0) | 2020.05.29 |
---|---|
클래스에서 개인 필드가 수정되는 것을 어떻게 방지합니까? (0) | 2020.05.29 |
선행 0으로 Java 문자열을 형식화하는 방법은 무엇입니까? (0) | 2020.05.29 |
Mac OSX Lion에서 PostgreSQL 9.0.4를 완전히 제거 하시겠습니까? (0) | 2020.05.29 |
전체 폴더와 내용을 삭제하는 방법? (0) | 2020.05.29 |