web-dev-qa-db-ja.com

2つのスライスの等価性を確認する

2つのスライスが等しいかどうかを確認するにはどうすればよいですか?

224
wei2912

スライス内の各要素をループしてテストする必要があります。スライスの等価性は定義されていません。ただし、タイプbytes.Equalの値を比較する場合は、[]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
}
132

reflect.DeepEqual() を使用する必要があります

DeepEqualは、Goの==演算子の再帰的な緩和です。

DeepEqualは、次のように定義されたxとyが「深く等しい」かどうかを報告します。次のいずれかのケースに該当する場合、同じタイプの2つの値は完全に等しくなります。特殊タイプの値が完全に等しくなることはありません。

配列の値は、対応する要素が完全に等しい場合に完全に等しくなります。

エクスポートされたものとエクスポートされていないものの両方の対応するフィールドが深く等しい場合、構造体の値は深く等しくなります。

両方がnilの場合、Func値は完全に等しくなります。それ以外の場合、それらは完全に同等ではありません。

インターフェース値は、深く等しい具象値を保持している場合、深く等しくなります。

マップ値が同じマップオブジェクトである場合、または同じ長さで、対応するキー(Go等式を使用して一致)が深く等しい値にマップされる場合、マップ値は深く等しくなります。

ポインターの値は、Goの==演算子を使用して等しいか、深く等しい値を指す場合、深く等しくなります。

次のすべてに該当する場合、スライス値は完全に等しくなります。両方ともnilまたは両方が非nilで、長さが同じで、同じ基になる配列の同じ初期エントリを指します(つまり&x [0 ] ==&y [0])または対応する要素(長さまで)は完全に等しい。空でないスライスと空のスライス(たとえば、[] byte {}と[] byte(nil))は深く等しくないことに注意してください。

他の値(数値、ブール値、文字列、チャネル)は、Goの==演算子を使用して等しい場合、完全に等しいです。

233
Victor Deryagin

これは、 reflect.DeepEqual() を使用した単なる例であり、@ VictorDeryaginの回答に記載されています。

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
34
Akavall

[]byteが2つある場合は、 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
16
KeksArmee

テストの作成に興味がある場合は、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
1

そして今のところ、 https://github.com/google/go-cmp

2つの値が意味的に等しいかどうかを比較するためのreflect.DeepEqualのより強力で安全な代替手段となることを目的としています。

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
}
0
lk_vc