用于计算递归定义的自定义类型的不同对象数的惯用方法

时间:2016-05-20 14:09:35

标签: dictionary recursion go set equality

据我了解,我无法在Go中定义用户定义类型的相等性。那么计算某些自定义类型(可能递归定义)的不同对象数量的惯用方法是什么呢?这是我想要做的事情的一个例子。

public static Collection<Order> readFromFile(String filePath) throws IOException {
    Map<String, Order> orderMap = new LinkedHashMap<>();
    List<String> lines = Files.readAllLines(Paths.get(filePath));

它可以工作,但字符串的使用非常难看,而且效率也很低。显然,我可以轻松编写一个递归方法来判断两棵树是否相等 - 比如

package main

import "fmt"

type tree struct {
    left  *tree
    right *tree
}

func shapeOf(a tree) string {
    temp := "{"
    if a.left != nil {
        temp += shapeOf(*(a.left))
    }
    temp += "}{"
    if a.right != nil {
        temp += shapeOf(*(a.right))
    }
    temp += "}"
    return temp;
}

func main() {
    a := tree{nil, nil}
    b := tree{nil, &a}

    c := tree{nil, nil}
    d := tree{nil, &c}

    e := tree{nil, nil}
    f := tree{&e, nil}

    s := make(map[string]bool)

    s[shapeOf(b)] = true
    s[shapeOf(d)] = true
    s[shapeOf(f)] = true
    fmt.Println(len(s)) // As required, prints 2 because the first two trees have the same shape
}

但是这不能让我使用树作为地图键。做这样的事情的惯用Go方式是什么?

1 个答案:

答案 0 :(得分:1)

您无法为用户定义的类型定义相等性,因为它已由go定义。基本上,所有有关它的信息都在comparable部分进行了解释。

简短的故事:如果可以比较它们的字段(没有切片,地图或函数),则可以比较两个结构值。同样的事情是平等:如果两个结构的字段相等,它们是相等的。在你的情况下,问题是,为了比较指针,Golang比较内存地址,而不是它们指向的结构。

那么,是否可以计算某个结构的不同值?是的,如果struct不包含嵌套切片,map,function或pointer。对于递归类型,这是不可能的,因为你不能定义这样的东西:

type tree struct {
    left tree
    right tree
}

测试递归类型相等性的惯用方法是使用reflect.DeepEqual(t1, t2 interface{}),因为它遵循间接性。然而,这种方法效率低,因为使用了大量反射。在您的情况下,我认为没有任何干净而优雅的解决方案可以满足您的需求。