Goのスライス(Go配列の実装)をGoマップのキーとして使用できないのはなぜですか。配列はキーとして使用できますか?ここでGoのスライスをGoマップのキーとして使用できないのは、配列をキーとして使用するのと同じですか?
答えて
はhttps://groups.google.com/forum/#!topic/golang-nuts/zYlx6sR4F8Yからのナイジェル・タオの答えです:
一つの理由は、配列は値型であるということです。
a0
は[N]int
( 配列)であれば、a1 := a0 a1[0] = 0
を行うことは全く
a0[0]
には影響しません。これに対して、スライスは、基本となる配列を参照しています。スライス の値をコピーすると、O(長さ)ではなくO(1)になります。
s0
は[]int
(スライス) であれば、s1 := s0 s1[0] = 0
を行うと、
s0[0]
が何であるかに影響します。http://play.golang.org/p/TVkntIsLo8
地図キーは平等のいくつかの概念を必要とします。配列の場合、これは単純に 要素同値です。スライスの場合、 は等価を定義する複数の方法があります.1つは要素ごとの等価、もう1つは と同じ配列のバッキングストアです。さらに、地図の挿入は にする必要がありますか?バッキングアレイ全体の(高価な)コピーを作成しますか? のコピーはおそらくあまり驚くことではありませんが、それは の割り当てと矛盾しています。
このコードスニペットはどのように印刷する必要がありますか?
m := make(map[[]int]bool) s0 := []int{6, 7, 8} s1 := []int{6, 7, 8} s2 := s0 m[s0] = true s2[0] = 9 println(m[s0]) println(m[s1]) println(m[s2])
異なるプログラマは、異なる期待を持つことができます。 の混乱を避けるため、今度は の地図キーとしてスライスを許可しないことにしました。
正確に答えるために:
comparison operators ==と=完全にキータイプのオペランドに定義する必要があります。 "なぜカントの?"!したがって、のキータイプは、の関数、マップ、またはスライスであってはなりません。
この仕様では、比較が定義されていないキータイプは許可されません。
スライス、マップ、および関数の値は、比較できないです:Spec: Comparison operatorsもこれを確認しました。
推論のために、smarxの答え(引用符はNigel Tao's answer)を参照してください。そして読んでください。
Goのマップはhashmapの実装を使用しています。一般に(プログラミング言語に関係なく)、ハッシュマップでキーとして使用される値を変更すると、未定義(または予期しない最小の)動作が発生する可能性があります。通常、キーのハッシュコードは、値(キーと値のペア)が配置されているバケットを指定するために使用されます。キーが変更され、そのキーに関連付けられた値を要求すると、実装は間違ったバケットを検索する可能性があります(したがって、見つからないことを報告する)。変更されたキー値は、異なるバケツ。
Goスライスは、基本となる配列の連続する部分の記述子であり、スライス値を割り当てるとこれらの記述子のみがコピーされます。したがって、スライスをキーとして使用すると、マップ実装はこのスライスヘッダー(基本配列の最初に参照される要素へのポインタ、長さ、および容量)のみをコピーすることが期待されます。ハッシュコンパイルと平等がこれらの3つの要素と他のものを使用する場合にのみ機能しますが、私たち(人間、プログラマー)にとって、スライスはスライスヘッダーを通じてアクセスできる要素を意味します - 変更することもできます)。
マップでスライスがキーとして機能するようにするには、適切に機能するために、スライス(キーとして使用される)のスライス要素が変更されるたびに内部状態とデータ構造を更新する必要があります予想された。
アレイはこの点でクールです。配列はすべての要素を意味します。配列をコピーするとすべての要素がコピーされ、比較は次のように定義されます。
配列要素の型の値が匹敵する場合、配列の値は匹敵します。対応する要素が等しい場合、2つの配列値は等しいです。
そして、あなたが前にキーとして使用される配列の要素を変更する場合(その改変体を有する)新しいアレイマップに格納され、使用される元に等しくないようにしない問題変更された配列で関連付けられた値を照会すると、結果が得られず、変更されていない元の配列で照会すると、以前に保管された値が正しく戻されます。
- 1. 構造体をGoマップのキーとして使用する
- 2. Goでは、キーごとにロックを使用してマップの各キーを同期できますか?
- 3. go langのマップから文字列配列としてキーを取得するには?
- 4. CouchDB:Reduceを使用しているときにマップ関数で配列キーを使用するには?
- 5. レコードセットのキーとして文字列の配列を使用できますか?
- 6. デバッグGOを使用してVSCodeでGO
- 7. Javascriptで配列をキーとして使用するには?
- 8. AppEngine for Goを使用しているときに、キーをレポから外しておく方法は?
- 9. 配列の内容をハッシュのキーとして使用できますか?
- 10. マップを反転しますが、キーとして値を使用し、値としてキーを使用します。
- 11. ビットセットをキーとしてマップを使用する際の問題
- 12. javascriptマップのキーとしての配列ですか?
- 13. キーと数値の配列を使用して文字列を分割することはできますか?
- 14. 口ひげテンプレートオブジェクトのキーとして使用し、配列値は
- 15. 複数のResourceDictionaryと同じDataTemplateキーを使用していますか?
- 16. NSLocalizedStringを辞書のキーとして使用できますか?
- 17. ThreadLocalをHashMapのキーとして使用できますか?
- 18. キー配列として列のいずれかを使用して、データベースから配列を取得します
- 19. なぜHashMapのキーとして文字列を使用できますか?
- 20. Go - 譲渡でタイプとして使用できません。
- 21. Javascript:配列キーが日付として使用されない
- 22. 数字をassoc配列キーとして使用する
- 23. int配列をキーとして使用するバイナリツリー(ユークリッド距離)?
- 24. 同じ配列キー名を使用したphp配列
- 25. Google GoとSQLite:使用するライブラリとその使い方は?
- 26. GoでMmapを使用してファイルに配列をマッピング
- 27. すべてのキーと値のペアの同じキーですか?
- 28. 2つの列を主キーとして使用するSQLでPivotを使用
- 29. Go:ソートされた配列のループ、sort.Sortが値として使用される
- 30. go getを使用してローカルリポジトリとプライベートリポジトリから取得する
スライスの平等性を比較できますか?いいえの場合は、それを使用することはできません。または、等価比較のない型をマップ内のキーとして使用することはできません。 – Arunmu