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


87

을 사용하여 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]'피연산자에 적용 할 수 없습니다.




안녕하세요 @ the-nomad, 수락 된 답변을 두 배 이상의 찬성표를 가진 답변으로 옮길 수 있습니까? :-)?
blackjacx

답변:


67
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를 참조하세요.


어디 넣을 수 있습니다 extension이 가지고 function내 코드에서 사용할 어디를? 미안해 내가 멍청이야!
The Nomad

1
프로젝트의 모든 파일에 넣어
슈오

값이 딕셔너리 인 경우 어떻게 딥 병합합니까?
Rodrigo Ruiz

@RodrigoRuiz 원본 사전이 동일한 아키텍처 인 한 아무런 차이가 없다고 생각합니다 (원래 사전이 유형이 아닌 경우 [Key: Any])
Septronic

2
Dictionary자체 병합 기능이 있으므로 확장이 더 이상 필요하지 않습니다 . stackoverflow.com/a/43615143/971329를 참조하십시오 .
blackjacx

161

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

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 새 사전을 반환합니다.

16

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등 간결한 코드의 스테이플입니다. 기능적인 부분은 재미 있습니다!


스위프트 2.2 컴파일러는 경고를 발생 : " 'var에'매개 변수는 사용되지 않으며 스위프트 3에서 제거 될 예정입니다"
Dheeraj Vepakomma

8
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]

7

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

6

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]

3

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

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

이 접근 방식 시도

    let dict1: [String: AnyObject] = ["kFacebook": ["kToken": "token"]]
    let dict2: [String: AnyObject] = ["kRequest": ["kTargetUserId": "userId"]]

    var combinedAttributes : NSMutableDictionary!

    combinedAttributes = NSMutableDictionary(dictionary: dict1)

    combinedAttributes.addEntriesFromDictionary(dict2)

    println(combinedAttributes)

다음과 같이 인쇄됩니다.

{
kFacebook =     {
    kToken = token;
};
kRequest =     {
    kTargetUserId = userId;
};

}

그것이 도움이되기를 바랍니다!


1

아래 코드를 사용하여 Swift에서 두 개의 사전 인스턴스를 결합 할 수 있습니다.

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
    }
}

-1

let 키워드를 사용하여 사전을 선언하므로 상수를 선언하는 데 사용되므로 사전을 변경할 수 없습니다.

var 키워드로 변경하면 작동합니다.

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

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

dict1 += dict2
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.