2つのマップの結合を実行する


81

ファイルパスを表すオブジェクトを作成する再帰関数があります(キーはパスであり、値はファイルに関する情報です)。ファイルの処理のみを目的としているため再帰的であるため、ディレクトリが検出されると、そのディレクトリで関数が再帰的に呼び出されます。

そうは言っても、2つのマップ(つまり、再帰呼び出しの値で更新された「メイン」マップ)で集合和集合に相当するものを実行したいと思います。1つのマップを繰り返し処理し、各キーとその値を他のマップの同じものに割り当てる以外に、これを行う慣用的な方法はありますか?

つまり、givena,bはタイプmap [string] *SomeObjectでありab最終的には入力さaれますが、b?のすべての値で更新する方法はありますか?


2
おそらく、このタイプの作業には実際のセットコンテナを利用できます:github.com/deckarep/golang-set
Ralph Caraveo 2014年

ラルフの提案はセットに適しています。ただし、あなたの場合は、マージであるほどユニオンではありません。セットは単に「キー」のコレクションである必要がありますが、キーと値のペアのコレクションが2つあり、一方の「セット」が他方よりも優先される必要があります。
アニサス2014年

回答:


132

このようなマージを行うための組み込みの方法も、標準パッケージのメソッドもありません。

理想的な方法は、単純に繰り返すことです。

for k, v := range b {
    a[k] = v
}

5
ANisusが答えたものに追加するには:マップは本質的にハッシュテーブルです。単に両方のマップを反復処理するよりも速く2つのマップの和集合を計算する方法はおそらくありません。
fuz 2014年

リフレクションを使用して、型に依存しないユニオン関数を作成することもできますが、速度は遅くなります。
エヴァン

このコードは、vをa [k]に割り当てる前に、a [k]とvの値をUNIONするべきではありませんか?a [k]とvが配列またはマップの場合はどうなりますか?
vdolez 2018年

2
彼は、必ずしもマップ内の値ではなく、マップを結合しようとしています。あなたがそのような何かをしたい場合は、あなただけ変更する必要があるa[k] = va[k] = a[k] + vか、そのような何か。
カイル

@カイル私はあなたが正しいと思います。実際のために労働組合、これを使用することができます:a[k] = append(a[k], v...)
user3405291

2

ネストされたマップのカップルを持っている、場合leftright、この関数は再帰的にからアイテムを追加しますrightleft。キーがすでに入っている場合はleft、構造の奥深くまで再帰し、キーの追加のみを試みますleft(たとえばキーを置き換えないでください)。


type m = map[string]interface{}

// Given two maps, recursively merge right into left, NEVER replacing any key that already exists in left
func mergeKeys(left, right m) m {
    for key, rightVal := range right {
        if leftVal, present := left[key]; present {
            //then we don't want to replace it - recurse
            left[key] = mergeKeys(leftVal.(m), rightVal.(m))
        } else {
            // key not in left so we can just shove it in
            left[key] = rightVal
        }
    }
    return left
}

注:値自体がmap[string]interface{}。でない場合は処理しません。したがって、持っleft["x"] = 1ているright["x"] = 2場合、上記のコードは試行時にパニックになりleftVal.(m)ます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.