挿入順序でマップをループする
Go のマップでは反復順序が保証されないため、項目を取得するときにイライラする可能性があります挿入された順序で。いくつかの回避策は存在しますが、多くの場合、個別のスライスを使用したり、データの重複を作成したりする必要があり、複雑さや潜在的なバグにつながる可能性があります。
キー スライスを使用した解決策
実行可能な 1 つの方法解決策は、キーのスライスを挿入順序で維持することです。新しいペアをマップに追加するときは、まずスライスにキーが存在するかどうかを確認します。そうでない場合は、キーをスライスに追加します。反復するときは、スライスを使用してキーを順番に取得し、マップから対応する値にアクセスするだけです。スライスにはキーのみが保存されるため、このアプローチのオーバーヘッドは最小限です。
例:
type Key int type Value int type OrderedMap struct { m map[Key]Value keys []Key } func NewOrderedMap() *OrderedMap { return &OrderedMap{m: make(map[Key]Value)} } func (om *OrderedMap) Set(k Key, v Value) { if _, ok := om.m[k]; !ok { om.keys = append(om.keys, k) } om.m[k] = v } func (om *OrderedMap) Range() { for _, k := range om.keys { fmt.Println(om.m[k]) } }
値ラッパーのリンク リストを使用したソリューション
または、リンクされたリスト構造で値をラップすることもできます。各値ラッパーには、実際の値とリスト内の次のキーへのポインターが含まれています。新しいペアを追加するときは、前の値ラッパーの次のポインターが新しいキーを指すように設定します。反復するときは、最初のキーから開始し、次のポインターに従って値を順番に取得します。
例:
type Key int type Value int type ValueWrapper struct { v Value next *Key } type OrderedMap struct { m map[Key]ValueWrapper first, last *Key } func NewOrderedMap() *OrderedMap { return &OrderedMap{m: make(map[Key]ValueWrapper)} } func (om *OrderedMap) Set(k Key, v Value) { if _, ok := om.m[k]; !ok && om.last != nil { pw2 := om.m[*om.last] om.m[*om.last] = ValueWrapper{pw2.v, &k} } pw := ValueWrapper{v: v} om.m[k] = pw if om.first == nil { om.first = &k } om.last = &k } func (om *OrderedMap) Range() { for k := om.first; k != nil; { pw := om.m[*k] fmt.Println(pw.v) k = pw.next } }
比較
キー スライスのアプローチは単純ですが、スライス内の線形検索が必要なため、要素の削除の効率は低くなります。値ラッパーのリンク リストのアプローチでは要素を迅速に削除できるため、頻繁な削除が予想される場合により適しています。
最終的に、最良の選択はアプリケーションの特定の要件によって異なります。
以上がGo マップを反復処理するときに挿入順序を維持するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。