Maison  >  Article  >  développement back-end  >  Comment comparer sémantiquement les structures et les tranches imbriquées quel que soit l'ordre des éléments dans Go

Comment comparer sémantiquement les structures et les tranches imbriquées quel que soit l'ordre des éléments dans Go

WBOY
WBOYavant
2024-02-10 18:39:10845parcourir

无论 Go 中元素的顺序如何,如何在语义上比较结构与嵌套切片

Quel que soit l'ordre des éléments dans Go, comment comparer sémantiquement les structures par rapport aux tranches imbriquées est une question courante. Dans le langage Go, une structure est un type de données agrégé, tandis qu'une tranche est un tableau dynamique. L'éditeur PHP Zimo répondra à cette question pour vous. Lorsque l'on compare des structures, elles ne sont comparables que si tous les membres sont de types comparables. Lors de la comparaison de tranches imbriquées, nous devons comparer les éléments des tranches niveau par niveau. Si les types d'éléments de la tranche ne sont pas comparables, nous devons utiliser une méthode récursive pour comparer chaque élément de la tranche. Qu'il s'agisse d'une structure ou d'une tranche imbriquée, nous pouvons comparer des éléments en les itérant.

Contenu de la question

Donnez la définition suivante de la structure de type :

type A struct {
    Id  int
    Bs  []B
    Sub C
}

type B struct {
    Id  int
    Str string
}

type C struct {
    Id int
    Ds []D
}

type D struct {
    Id  int
    Num int
}

Je souhaite tester si les deux instances suivantes de A sont sémantiquement égales quel que soit l'ordre des éléments de tranche à tous les niveaux hiérarchiques.

var want = &A{
    Id: 1,
    Bs: []B{{Id: 10, Str: "b10"}, {Id: 20, Str: "b20"}},
    Sub: C{
        Id: 100,
        Ds: []D{{Id: 101, Num: 1001}, {Id: 102, Num: 1002}},
    },
}

var got = &A{
    Id: 1,
    Bs: []B{{Id: 20, Str: "b20"}, {Id: 10, Str: "b10"}},
    Sub: C{
        Id: 100,
        Ds: []D{{Id: 102, Num: 1002}, {Id: 101, Num: 1001}},
    },
}

Affirmez que la comparaison doit renvoyer true

Solution de contournement

Le package cmp est destiné à être un remplacement plus puissant et plus sûr de reflect.DeepEqual pour comparer deux valeurs pour l'égalité sémantique.

Voici une implémentation complète de la comparaison structurelle d'égalité sémantique quel que soit l'ordre des éléments de tranche à tous les niveaux hiérarchiques.

Fichier source.go

package main

type A struct {
    Id  int
    Bs  []B
    Sub C
}

type B struct {
    Id  int
    Str string
}

type C struct {
    Id int
    Ds []D
}

type D struct {
    Id  int
    Num int
}

func NewA() *A {
    return &A{
        Id: 1,
        Bs: []B{{Id: 20, Str: "b20"}, {Id: 10, Str: "b10"}},
        Sub: C{
            Id: 100,
            Ds: []D{{Id: 102, Num: 1002}, {Id: 101, Num: 1001}},
        },
    }
}

Fichier source_test.go

package main

import (
    "fmt"
    "testing"

    "github.com/google/go-cmp/cmp"
    "github.com/google/go-cmp/cmp/cmpopts"
)

var want = &A{
    Id: 1,
    Bs: []B{{Id: 10, Str: "b10"}, {Id: 20, Str: "b20"}},
    Sub: C{
        Id: 100,
        Ds: []D{{Id: 101, Num: 1001}, {Id: 102, Num: 1002}},
    },
}

func TestNewA(t *testing.T) {
    got := NewA()
    less := func(x, y any) bool {
        switch xv := x.(type) {
        case B:
            yv := y.(B)
            return fmt.Sprintf("%d-%s", xv.Id, xv.Str) < fmt.Sprintf("%d-%s", yv.Id, yv.Str)
        case D:
            yv := y.(D)
            return fmt.Sprintf("%d-%d", xv.Id, xv.Num) < fmt.Sprintf("%d-%d", yv.Id, yv.Num)
        default:
            return false
        }
    }
    if diff := cmp.Diff(want, got, cmpopts.SortSlices(less)); diff != "" {
        t.Errorf("mismatch:\n%s", diff)
    }
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer