2つのスライスが等しいかどうかを確認するにはどうすればよいですか?
slice can only be compared to nil
、スライスの等価性をチェックする慣用的なgolangの方法があるかどうか疑問に思っていました...等価演算子が言語によって定義されていない場合、最も効率的な方法を尋ねるのが妥当だと思いますそれを達成するために。質問を閉じる必要はありませんでした
2つのスライスが等しいかどうかを確認するにはどうすればよいですか?
slice can only be compared to nil
、スライスの等価性をチェックする慣用的なgolangの方法があるかどうか疑問に思っていました...等価演算子が言語によって定義されていない場合、最も効率的な方法を尋ねるのが妥当だと思いますそれを達成するために。質問を閉じる必要はありませんでした
回答:
スライスの各要素をループしてテストする必要があります。スライスの等価性は定義されていません。ただし、bytes.Equal
typeの値を比較する場合は関数があります[]byte
。
func testEq(a, b []Type) bool {
// If one is nil, the other must also be nil.
if (a == nil) != (b == nil) {
return false;
}
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
for i, v := range a { if v != b[i] { return false } }
。
あなたは使うべきです reflect.DeepEqual()
DeepEqualは、Goの==演算子の再帰的な緩和です。
DeepEqualは、xとyが「深く等しい」かどうかを報告します。以下のように定義されています。同じタイプの2つの値は、次のいずれかの場合が当てはまる場合、完全に等しくなります。特殊タイプの値が深く等しくなることはありません。
配列の値は、対応する要素が深く等しい場合に深く等しくなります。
エクスポートされる値とエクスポートされない値の両方に対応するフィールドが深く等しい場合、構造体の値は深く等しくなります。
両方がnilの場合、Func値は深く等しくなります。そうでなければ、それらは深くは等しくありません。
インターフェースの値は、具体的な値が深く等しい場合、深く等しくなります。
マップ値は、それらが同じマップオブジェクトである場合、またはそれらが同じ長さで、対応するキー(Go等式を使用して一致する)が深く等しい値にマップされている場合、深く等しくなります。
ポインターの値は、Goの==演算子を使用して等しい場合、または深く等しい値を指している場合、深く等しくなります。
スライス値は、次のすべてが真である場合に深く等しくなります。両方ともnilまたは両方とも非nilであり、それらは同じ長さであり、同じ基本配列の同じ初期エントリを指している(つまり、&x [0 ] ==&y [0])または対応する要素(長さまで)が深く等しい。nil以外の空のスライスとnilスライス(たとえば、[] byte {}と[] byte(nil))は完全には等しくないことに注意してください。
他の値-数値、ブール値、文字列、チャネル-は、Goの==演算子を使用して等しい場合、完全に等しくなります。
これは、@ VictorDeryaginの回答で示されているReflect.DeepEqual()を使用した単なる例です。
package main
import (
"fmt"
"reflect"
)
func main() {
a := []int {4,5,6}
b := []int {4,5,6}
c := []int {4,5,6,7}
fmt.Println(reflect.DeepEqual(a, b))
fmt.Println(reflect.DeepEqual(a, c))
}
結果:
true
false
2つある場合は[]byte
、bytes.Equalを使用して比較します。Golangのドキュメントによれば、
Equalは、aとbが同じ長さで、同じバイトを含むかどうかを報告するブール値を返します。nil引数は空のスライスと同等です。
使用法:
package main
import (
"fmt"
"bytes"
)
func main() {
a := []byte {1,2,3}
b := []byte {1,2,3}
c := []byte {1,2,2}
fmt.Println(bytes.Equal(a, b))
fmt.Println(bytes.Equal(a, c))
}
これは印刷されます
true
false
そして今のところ、これはhttps://github.com/google/go-cmpです
reflect.DeepEqual
2つの値が意味的に等しいかどうかを比較するためのより強力で安全な代替手段となることを目的としています。
package main
import (
"fmt"
"github.com/google/go-cmp/cmp"
)
func main() {
a := []byte{1, 2, 3}
b := []byte{1, 2, 3}
fmt.Println(cmp.Equal(a, b)) // true
}
テストを書くことに興味がある場合は、 github.com/stretchr/testify/assert
は、あなたの友達です。
ファイルの最初にライブラリをインポートします。
import (
"github.com/stretchr/testify/assert"
)
次に、あなたが行うテストの中で:
func TestEquality_SomeSlice (t * testing.T) {
a := []int{1, 2}
b := []int{2, 1}
assert.Equal(t, a, b)
}
要求されるエラーは次のとおりです。
Diff:
--- Expected
+++ Actual
@@ -1,4 +1,4 @@
([]int) (len=2) {
+ (int) 1,
(int) 2,
- (int) 2,
(int) 1,
Test: TestEquality_SomeSlice
assert.Equal
内部で使用しreflect.DeepEqual
ているため、テストの実行が遅くなり、最終的にはパイプラインが実行される可能性があります。
==
オペレータはそうしかも、この質問にも正当な一つであり、唯一のいくつかのタイプのために行くに定義されています。