web-dev-qa-db-ja.com

Swiftで2つのDictionaryインスタンスを組み合わせる方法は?

Dictionaryを使用して、あるDictionaryを別のSwiftに追加するにはどうすればよいですか?

AlamoFireライブラリを使用してJSONREST serverに送信しています。

辞書1

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

辞書2

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

以下に示すように2つの辞書を組み合わせて新しい辞書を作成するにはどうすればよいですか?

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

dict1 += dict2を試しましたが、コンパイルエラーが発生しました。

二項演算子「+ =」は、2つの「[String:AnyObject]」オペランドに適用できません

49
The Nomad
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

40
Shuo

私はこのアプローチが大好きです:

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

Swift 4および5

With Swift 4 Appleは、2つの辞書をマージするためのより良いアプローチを導入します。

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]

ここには2つのオプションがあります(コンテナで動作するほとんどの機能と同様):

  • mergeは既存の辞書を変更します
  • mergingは新しい辞書を返します
82
blackjacx

SequenceType.forEachDictionaryで実装)は、辞書の要素を別の辞書に追加するエレガントなソリューションを提供します。

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

例えば

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

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

    XCTAssertEqual(dic2[1], "foo")
}
5
rhooke
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]
4
Leo Dabus

私のニーズは異なっていたので、合併するのではなく統合したかったのです。

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
Chris Conover

このアプローチを試してください

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

}

それが役に立てば幸い !!

2
Wolverine

以下のコードを使用して、Swiftで2つの辞書インスタンスを組み合わせることができます。

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