Go中的切片迭代顺序

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

slice iteration order in go

问题

好的,以下是翻译的内容:

好的,我认为这可能是一个旧问题,但我在stackoverflow上没有找到任何相关内容。在Go语言中,对映射进行迭代的顺序不能保证是可复现的。因此,建议的方法是将键保存在一个切片中,并对该切片进行排序。然后通过对该切片进行迭代来从映射中检索值,以便按顺序获取它们(因为由键组成的切片是排序的,所以将按可复现的顺序排列)。这就意味着切片需要被排序,否则对切片的迭代也无法给出可复现的顺序。但是当我在playground中尝试下面的代码时,我总是发现迭代中的顺序保持不变,那么在映射迭代的情况下,为什么需要对键的切片进行排序呢?

func main() {
    var mySlice = make([]string, 0)
    mySlice = append(mySlice, "abcd")
    mySlice = append(mySlice, "efgh")
    mySlice = append(mySlice, "ijkl")
    mySlice = append(mySlice, "mnop")
    mySlice = append(mySlice, "qrst")
    mySlice = append(mySlice, "uvwxyz")
    for _, val := range mySlice {
        fmt.Println(val)
    }
    fmt.Println(strings.Join(mySlice, "|"))
}

输出:

abcd
efgh
ijkl
mnop
qrst
uvwxyz
abcd|efgh|ijkl|mnop|qrst|uvwxyz
英文:

Ok, i think this may be an old question, but i didn't find anything over the stackoverflow. In go , the iteration order over a map is not guranteed to be reproducible. So, the way suggest is to hold the keys in a slice and sort that slice. Then iterate over that slice to retrieve the values from the map, so that we get them in order(since slice composed of keys is sorted, so will be in reproducible order). So this goes to imply that the slice need be sorted else iteration over the slice will also not give reproducible order. But when i tried the below code in playground, i always found the order maintained in iteration, then in the map iteration case, why the slice of keys need to be sorted?

func main() {
	var mySlice = make([]string, 0)
	mySlice = append(mySlice, "abcd")
	mySlice = append(mySlice, "efgh")
	mySlice = append(mySlice, "ijkl")
	mySlice = append(mySlice, "mnop")
	mySlice = append(mySlice, "qrst")
	mySlice = append(mySlice, "uvwxyz")
	for _, val := range mySlice {
		fmt.Println(val)
	}
	fmt.Println(strings.Join(mySlice, "|"))

}

Output:

abcd
efgh
ijkl
mnop
qrst
uvwxyz
abcd|efgh|ijkl|mnop|qrst|uvwxyz

答案1

得分: 16

一个切片或数组总是有一个固定的顺序,即它在内存中的布局方式。

你阅读的文档可能只是告诉你对切片进行排序,以便使映射的输出按照排序顺序排列。

你是正确的,映射的迭代顺序是未定义的,因此每次执行时可能会有所不同。如果你使用一个切片来迭代一个映射,那么它将始终以可靠的顺序返回,即切片中键的顺序。

我建议你阅读一下关于切片的信息。

编辑

如果有帮助的话,考虑以下代码来说明切片的排序与其顺序固定无关:

words := map[int]string{
    0: "hello",
    1: "there",
    2: "goodbye",
}
keys := []int{2, 0, 1}
for _, k := range keys {
    // 输出的顺序为:Goodbye, hello, there
    fmt.Println("Key:", k, "Value:", words[k])
}
英文:

A slice or array will always have a fixed order, i.e. how it is laid out in memory.

The documentation you were reading was probably just telling you to sort the slice so that the map output is in sorted order.

You are correct that the iteration order of a map is undefined and hence can be different each time it is performed. If you use a slice to iterate a map then it will always come back in a reliable order, i.e. the order of the keys in the slice.

I suggest you have a read over the information about slices.

EDIT

If it helps, consider the following code to illustrate that the sorting of a slice has nothing to do with its order being fixed:

words := map[int]string{
    0: "hello",
    1: "there",
    2: "goodbye",
}
keys:=[]int{2,0,1}
for _, k := range keys {
    // Will output in order: Goodbye, hello, there
    fmt.Println("Key:", k, "Value:", words[k])
}

答案2

得分: 7

你的切片之所以排序是因为你按照已排序的顺序添加了项目。如果你按照未排序的顺序添加项目,例如:

var mySlice = make([]string, 0)
mySlice = append(mySlice, "mnop")
mySlice = append(mySlice, "efgh")
mySlice = append(mySlice, "uvwxyz")
mySlice = append(mySlice, "ijkl")
mySlice = append(mySlice, "abcd")
mySlice = append(mySlice, "qrst")

(或者通过从映射中提取键来填充切片,这将是无序的),那么迭代的顺序将是无序的(是一致的,但是一致地无序)。因此,如果你的目标是使用切片按排序顺序从映射中提取项目,那么你需要先对切片进行排序,除非你能保证切片项已按已排序的顺序插入。

英文:

The only reason your slice is sorted is because you're appending items in already sorted order. If you appended items in an unsorted order like this

var mySlice = make([]string, 0)
mySlice = append(mySlice, "mnop")
mySlice = append(mySlice, "efgh")
mySlice = append(mySlice, "uvwxyz")
mySlice = append(mySlice, "ijkl")
mySlice = append(mySlice, "abcd")
mySlice = append(mySlice, "qrst")

(or populated a slice by pulling keys from a map, which would be unsorted), then the order on iteration would be unsorted (consistent, yes, but consistently unsorted). So, if your objective is to use the slice to pull items from a map in sorted order, then you need to first sort the slice, unless you can guarantee the slice items were inserted in an already sorted order.

huangapple
  • 本文由 发表于 2017年7月27日 17:28:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/45346641.html
匿名

发表评论

匿名网友

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

确定