在Go语言中的N叉树

huangapple go评论87阅读模式
英文:

N-ary tree in Go

问题

我正在评估使用Go替代Node.js基础架构,并且我不确定如何创建表示N叉树的结构。

在JavaScript中,我解析一个文件来构建任意深度的地理位置层次结构。这是一个示例:

{
  'country1': {
    'area1': {
      'town1': {}, 
      'town2': {}
    },
    'area2': {
      'town3': {}
    }
  }
}

城镇可以扩展到具体的道路等。层次结构没有固定的深度。

我该如何在Go中创建一个等效的结构?

英文:

I am evaluating Go to replace Node.js infrastructure and I am not sure how to create a structure to represent a N-ary tree.

In JavaScript, I parse a file to build up a hierarchy of geographic locations of arbitrary depth. Here is an example:

{
  'country1': {
    'area1': {
      'town1': {}, 
      'town2': {}
    },
    'area2': {
      'town3': {}
    }
  }
}

Towns could expand into specific roads and so on. The hierarchy doesn't have a fixed depth.

How can I create an equivalent structure in Go?

答案1

得分: 3

如果你要有任意深度的结构,那么创建一个可以嵌套的默认结构可能是值得的:

type area struct {
    Name     string
    // 其他区域信息
    Sections []*area
}

在创建新的结构对象时,指针切片不会被初始化,所以这是一个有效的构造方式。声明 a.Sections = new([]*area) 并将 area 的指针追加到其中。你可以使用 len(a.Sections)for range 循环来进行树遍历。

解析和遍历可以使用递归编码,所以如果你以不同的方式处理不同的区域,你将需要一个类型标识符。

英文:

If you're going to have arbitrary depth, then it might be worth it to create a default struct that can be nested:

type area struct {
    Name string
    //Any other area info
    Sections []*area
}

Slices of pointers aren't initialized when creating a new struct object, so it's a valid construct. Declare a.Sections = new([]*area) and append area pointers to it. You will have len(a.Sections) or a for range loop for use in the tree traversal.

Parsing and traversal would be coded recursively, so you would need a type identifier if you treat different areas in different ways.

答案2

得分: 2

让我们来回顾一下这个层次结构。

  • 在顶层,你将国家名称映射到国家对象。

  • 每个国家对象将区域名称映射到区域对象。

  • 每个区域对象将城镇名称映射到城镇对象。

在Go语言中,你可以将层次结构的每个级别实现为map[string]*Something,其中最后一级由包含有关城镇的各种信息的Town对象组成:

type Country map[string]*Area

type Area map[string]*Town

type Town struct {
	Name                string
	Population          int
	Latitude, Longitude float64
}

你在问题中给出的示例层次结构将如下所示:

countries := map[string]*Country{
    "country1": &Country{
        "area1": &Area{
            "town1": &Town{},
            "town2": &Town{},
        },
        "area2": &Area{
            "town3": &Town{},
        },
    },
}

如果你不想映射到具体类型,可以使用map[string]interface{},但是你将需要使用类型断言来处理值。以下是从Zack Bloom的关于Go和JSON的文章中摘取的代码示例:

var parsed map[string]interface{}
data := []byte(`
    {
        "id": "k34rAT4",
        "age": 24
    }
`)
err := json.Unmarshal(data, &parsed)
idString := parsed["id"].(string)
英文:

Let's review the hierarchy.

  • At the top level, you map country names to country objects.

  • Each country object maps area names to area objects.

  • Each area object maps town names to town objects.

In Go, you can implement each level of the hierarchy as a map[string]*Something, with the last level consisting of Town objects that contain various information about towns:

type Country map[string]*Area

type Area map[string]*Town

type Town struct {
	Name                string
	Population          int
	Latitude, Longitude float64
}

The sample hierarchy that you've given in your question would then look like this:

countries := map[string]*Country{
	"country1": &Country{
		"area1": &Area{
			"town1": &Town{},
			"town2": &Town{},
		},
		"area2": &Area{
			"town3": &Town{},
		},
	},
}

If you don't want to map to concrete types, you can use map[string]interface{}, but then you'll need type assertions to work with the values. Here is a code sample taken from Zack Bloom's article on Go and JSON:

var parsed map[string]interface{}
data := []byte(`
    {
        "id": "k34rAT4",
        "age": 24
    }
`)
err := json.Unmarshal(data, &parsed)
idString := parsed["id"].(string)

huangapple
  • 本文由 发表于 2015年9月22日 07:11:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/32705948.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定