【问题标题】:slice iteration order in gogo中的切片迭代顺序
【发布时间】:2017-07-27 09:28:01
【问题描述】:

好的,我认为这可能是一个老问题,但我没有在 stackoverflow 上找到任何东西。在 go 中,不能保证地图上的迭代顺序是可重现的。因此,建议的方法是将键保存在切片中并对该切片进行排序。然后遍历该切片以从映射中检索值,以便我们按顺序获取它们(因为由键组成的切片已排序,因此将按可重现的顺序)。所以这意味着需要对切片进行排序,否则切片上的迭代也不会给出可重现的顺序。但是当我在操场上尝试下面的代码时,我总是发现在迭代中保持顺序,那么在 map 迭代的情况下,为什么需要对键的切片进行排序?

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

【问题讨论】:

  • 你把切片和地图混在一起了。

标签: go slice


【解决方案1】:

您的切片已排序的唯一原因是您要以已排序的顺序附加项目。如果您像这样以未排序的顺序附加项目

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")

(或通过从地图中提取键来填充切片,这将是未排序的),那么迭代的顺序将是未排序的(一致的,是的,但始终未排序)。因此,如果您的目标是使用切片按排序顺序从地图中提取项目,那么您需要首先对切片进行排序,除非您可以保证切片项目以已排序的顺序插入。

【讨论】:

    【解决方案2】:

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

    您正在阅读的文档可能只是告诉您对切片进行排序,以便地图输出按排序顺序。

    您是正确的,地图的迭代顺序是未定义的,因此每次执行时都可能不同。如果您使用切片来迭代地图,那么它将始终以可靠的顺序返回,即切片中键的顺序。

    我建议您阅读有关slices 的信息。

    编辑

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

    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])
    }
    

    【讨论】:

    • 这是我想分享的链接:nathanleclaire.com/blog/2014/04/27/… 它提到在迭代之前对键切片进行排序。如果切片顺序是固定的,那为什么还要全部排序呢?
    • 在文章中,切片是通过迭代地图来构建的,因此切片将以随机顺序填充。他对切片进行了排序,以便键始终以相同的数字升序排列。切片中条目的顺序是固定的。如果您删除排序命令并添加无数个循环副本,您将看到地图中将返回相同顺序的元素。你只是不知道这个顺序是什么,因为键附加到切片的顺序是随机的。
    猜你喜欢
    • 2022-01-22
    • 1970-01-01
    • 2023-01-08
    • 2019-07-23
    • 2010-11-23
    • 2013-08-05
    • 1970-01-01
    • 2017-10-22
    • 2015-06-08
    相关资源
    最近更新 更多