[ios] Swift에서 두 개의 Dictionary 인스턴스를 결합하는 방법은 무엇입니까?

을 사용하여 Dictionary서로 DictionarySwift어떻게 추가 합니까?

내가 사용하고 AlamoFire을 보내 라이브러리를 JSONA를 REST server.

사전 1

var dict1: [String: AnyObject] = [
        kFacebook: [
            kToken: token
        ]
    ]

사전 2

var dict2: [String: AnyObject] = [
        kRequest: [
            kTargetUserId: userId
        ]
    ]

두 사전을 결합하여 아래와 같이 새 사전을 만들려면 어떻게해야합니까?

let parameters: [String: AnyObject] = [
        kFacebook: [
            kToken: token
        ],
        kRequest: [
            kTargetUserId: userId
        ]
    ]

시도 dict1 += dict2했지만 컴파일 오류가 발생했습니다.

이항 연산자 ‘+ =’는 두 개의 ‘[String : AnyObject]’피연산자에 적용 할 수 없습니다.



답변

var d1 = ["a": "b"]
var d2 = ["c": "e"]

extension Dictionary {
    mutating func merge(dict: [Key: Value]){
        for (k, v) in dict {
            updateValue(v, forKey: k)
        }
    }
}

d1.merge(d2)

멋진 Dollar & Cent 프로젝트
https://github.com/ankurp/Cent/blob/master/Sources/Dictionary.swift를 참조하세요.


답변

저는이 접근 방식을 좋아합니다.

dicFrom.forEach { (key, value) in dicTo[key] = value }

Swift 4 및 5

Swift 4를 통해 Apple은 두 개의 사전을 병합하는 더 나은 접근 방식을 도입했습니다.

let dictionary = ["a": 1, "b": 2]
let newKeyValues = ["a": 3, "b": 4]

let keepingCurrent = dictionary.merging(newKeyValues) { (current, _) in current }
// ["b": 2, "a": 1]

let replacingCurrent = dictionary.merging(newKeyValues) { (_, new) in new }
// ["b": 4, "a": 3]

여기에는 두 가지 옵션이 있습니다 (대부분의 컨테이너에서 작동하는 기능과 마찬가지로).

  • merge 기존 사전을 변경합니다.
  • merging 새 사전을 반환합니다.


답변

Swift> = 2.2의 경우 :
let parameters = dict1.reduce(dict2) { r, e in var r = r; r[e.0] = e.1; return r }

Swift <2.2의 경우 :
let parameters = dict1.reduce(dict2) { (var r, e) in r[e.0] = e.1; return r }

Swift 4에는 새로운 기능이 있습니다.
let parameters = dict1.reduce(into: dict2) { (r, e) in r[e.0] = e.1 }

그것은 표준 라이브러리 주위를 파고 정말 중요 : map, reduce, dropFirst, forEach등 간결한 코드의 스테이플입니다. 기능적인 부분은 재미 있습니다!


답변

func +=<Key, Value> (lhs: inout [Key: Value], rhs: [Key: Value]) {
    rhs.forEach{ lhs[$0] = $1 }
}

var dic1 = ["test1": 1]

dic1 += ["test2": 2]

dic1  // ["test2": 2, "test1": 1]


답변

SequenceType.forEach(에 의해 구현 됨 Dictionary) 사전의 요소를 다른 사전에 추가하는 우아한 솔루션을 제공합니다.

dic1.forEach { dic2[$0] = $1 }

예를 들면

func testMergeDictionaries() {
    let dic1 = [1:"foo"]
    var dic2 = [2:"bar"]

    dic1.forEach { dic2[$0] = $1 }

    XCTAssertEqual(dic2[1], "foo")
}


답변

merge 키워드를 사용하여 더 나은 방법으로 사전을 병합 할 수 있습니다.

var dictionary = ["a": 1, "b": 2]
/// Keeping existing value for key "a":
dictionary.merge(["a": 3, "c": 4]) { (current, _) in current }
 // ["b": 2, "a": 1, "c": 4]


답변

내 요구 사항은 달랐고, 합병을 원했고 엉망진창이 아니 었습니다.

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)")