猿问

检查一个地图是否是另一个地图的子集

这个问题已经以许多其他语言得到回答。在golang中,使用简单的地图(无嵌套)如何找出一个地图是否是另一个地图的子集。例如:是 的子集。我想要一个通用方法。我的代码:map[string]string{"a": "b", "e": "f"}map[string]string{"a": "b", "c": "d", "e": "f"}


package main


import (

    "fmt"

    "reflect"

)


func main() {

    a := map[string]string{"a": "b", "c": "d", "e": "f"}

    b := map[string]string{"a": "b", "e": "f"}

    c := IsMapSubset(a, b)

    fmt.Println(c)

}


func IsMapSubset(mapSet interface{}, mapSubset interface{}) bool {


    mapSetValue := reflect.ValueOf(mapSet)

    mapSubsetValue := reflect.ValueOf(mapSubset)


    if mapSetValue.Kind() != reflect.Map || mapSubsetValue.Kind() != reflect.Map {

        return false

    }

    if reflect.TypeOf(mapSetValue) != reflect.TypeOf(mapSubsetValue) {

        return false

    }

    if len(mapSubsetValue.MapKeys()) == 0 {

        return true

    }


    iterMapSubset := mapSubsetValue.MapRange()


    for iterMapSubset.Next() {

        k := iterMapSubset.Key()

        v := iterMapSubset.Value()


        if value := mapSetValue.MapIndex(k); value == nil || v != value { // invalid: value == nil

            return false

        }

    }


    return true

}

当我想检查子集映射键是否存在于集合映射中时,返回零类型的值,并使其无法与任何内容进行比较。MapIndex


毕竟,我能把同样的工作做得更好吗?


慕工程0101907
浏览 142回答 3
3回答

LEATH

我想要一个通用方法。现在Go 1.18和泛型在这里,你可以写这样一个泛型函数;见下文和这个游乐场。通常不鼓励进行反射,实现此功能不需要反射。package mainimport "fmt"func IsMapSubset[K, V comparable](m, sub map[K]V) bool {    if len(sub) > len(m) {        return false    }    for k, vsub := range sub {        if vm, found := m[k]; !found || vm != vsub {            return false        }    }    return true}type MyMap map[string]stringfunc main() {    a := map[string]string{"a": "b", "c": "d", "e": "f"}    b := map[string]string{"a": "b", "e": "f"}    c := map[string]string{"a": "b", "e": "g"}    fmt.Println(IsMapSubset(a, b))    fmt.Println(IsMapSubset(a, c))    fmt.Println(IsMapSubset(MyMap(a), c))}输出:truefalse不过,关于NaN的常见警告适用。

人到中年有点甜

Value.MapIndex() 返回一个反射。值,它是一个结构,不是结构的有效值。不能将结构值与 进行比较。nilnilValue.MapIndex()声明:如果在映射中找不到键,或者如果 v 表示 nil 映射,则返回零值。因此,要判断是否在映射中找不到该键,请检查返回的键是否为其零值。为此,您可以使用 Value.IsValid() 方法。reflect.Value您也不能(不应该)比较值。而是使用 Value.Interface() 获取其包装值,并对其进行比较。reflect.Valueif v2 := mapSetValue.MapIndex(k); !v2.IsValid() || v.Interface() != v2.Interface() {    return false}测试它:a := map[string]string{"a": "b", "c": "d", "e": "f"} b := map[string]string{"a": "b", "e": "f"} fmt.Println(IsMapSubset(a, b)) c := map[string]string{"a": "b", "e": "X"} fmt.Println(IsMapSubset(a, c))输出将是(在Go Playground上尝试):truefalse

蓝山帝景

这是工作解决方案,以防有人需要:// IsMapSubset returns true if mapSubset is a subset of mapSet otherwise falsefunc IsMapSubset(mapSet interface{}, mapSubset interface{}) bool {&nbsp; &nbsp; mapSetValue := reflect.ValueOf(mapSet)&nbsp; &nbsp; mapSubsetValue := reflect.ValueOf(mapSubset)&nbsp; &nbsp; if fmt.Sprintf("%T", mapSet) != fmt.Sprintf("%T", mapSubset) {&nbsp; &nbsp; &nbsp; &nbsp; return false&nbsp; &nbsp; }&nbsp; &nbsp; if len(mapSetValue.MapKeys()) < len(mapSubsetValue.MapKeys()) {&nbsp; &nbsp; &nbsp; &nbsp; return false&nbsp; &nbsp; }&nbsp; &nbsp; if len(mapSubsetValue.MapKeys()) == 0 {&nbsp; &nbsp; &nbsp; &nbsp; return true&nbsp; &nbsp; }&nbsp; &nbsp; iterMapSubset := mapSubsetValue.MapRange()&nbsp; &nbsp; for iterMapSubset.Next() {&nbsp; &nbsp; &nbsp; &nbsp; k := iterMapSubset.Key()&nbsp; &nbsp; &nbsp; &nbsp; v := iterMapSubset.Value()&nbsp; &nbsp; &nbsp; &nbsp; value := mapSetValue.MapIndex(k)&nbsp; &nbsp; &nbsp; &nbsp; if !value.IsValid() || v.Interface() != value.Interface() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return true}
随时随地看视频慕课网APP

相关分类

Go
我要回答