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


87

を使用Dictionaryして相互に追加するにはどうすればよいですか?DictionarySwift

AlamoFireライブラリを使用してをに送信しJSONていREST 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]'オペランドに適用することはできません




ねえ@ the-nomad、あなたはあなたの受け入れられた答えを2倍以上の賛成票を持つものに移すことができます-お願いします:-)?
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コードのどこでも利用できるようにするには、どこに置くことができますか?すみません、私は初心者です!
遊牧民2014年

1
プロジェクト内の任意のファイルに入れてください
Shuo

値が辞書でもある場合、どのように深くマージしますか?
ロドリゴルイス

@RodrigoRuiz元の辞書も同じアーキテクチャである限り、違いはないと思います(元の辞書がタイプでない限り[Key: Any]
Septronic 2018

2
Dictionary独自のマージ関数を取得したため、拡張機能は不要になりました。stackoverflow.com/a/43615143/971329を参照してください。
blackjacx

161

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

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

Swift4および5

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 新しい辞書を返します

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 }

Swift4には新しい機能があります。 let parameters = dict1.reduce(into: dict2) { (r, e) in r[e.0] = e.1 }

これは、標準ライブラリの周りに掘ることは本当に重要です:mapreducedropFirstforEachなど簡潔なコードのステープルです。機能的なビットは楽しいです!


Swift 2.2コンパイラは警告をスローします:「 'var'パラメータは非推奨であり、Swift 3で削除されます」
Dheeraj Vepakomma 2016

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

マージキーワードを使用して、より良い方法で辞書をマージできます

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

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