有没有一种方法可以在Go中反向迭代切片?


95

可以这样说:

for _, element := reverse range mySlice {
        ...
}

Answers:


139

没有,没有方便的运算符可将其添加到适当的范围1中。您必须对循环进行递减计数,这是正常的:

s := []int{5, 4, 3, 2, 1}
for i := len(s)-1; i >= 0; i-- {
   fmt.Println(s[i])
}

有效的去页的例子,但是这一次实际上是更好一点,并声明的变量较少。
凯文·坎特威尔

3
IMO Go迫切需要一个下降范围的构造。没有它会导致额外的工作一个很好的协议,我们可以看到... -
矢量

24
我不会拼命地说,这将是一个不错的选择。
亚当·库基维奇

46

您也可以这样做:

s := []int{5, 4, 3, 2, 1}
for i := range s {
        fmt.Println(s[len(s)-1-i]) // Suggestion: do `last := len(s)-1` before the loop
}

输出:

1
2
3
4
5

也在这里:http : //play.golang.org/p/l7Z69TV7Vl


13

指数变化

for k := range s {
        k = len(s) - 1 - k
        // now k starts from the end
    }

6

如何使用延期:

s := []int{5, 4, 3, 2, 1}
for i, _ := range s {
   defer fmt.Println(s[i])
}

8
我为它带来了一些新的知识defer而投票,但是我相信在循环中将其用于反向操作是非常棘手的,并且在内存方面应该是非常无效的。
亚历山大·特拉希梅诺克

10
它“有效”,但是如果循环不是函数中的最后一件事,则可能会得到意外的结果。例。
丹尼尔(Daniel)

5
这是以defer不适合的方式使用的。不要使用它,因为它可能会带来讨厌的副作用(乱序执行)。只需for在接受的答案中使用循环即可。Go的目标是尽量减少这种聪明的(不是)hack,因为它们以后会咬你的屁股。
RickyA

4
这是推迟使用的恶意手段,应避免使用。例如,如果这是某人将来可能扩展的功能,则可能会产生意想不到的后果。
阿米尔·基比

4
这还不够“灵活”,所以我继续添加频道play.golang.org/p/GodEiv1LlIJ
Xeoncross

4

可以使用一个通道来反转函数中的列表,而无需复制它。就我而言,它使代码更好。

package main

import (
    "fmt"
)

func reverse(lst []string) chan string {
    ret := make(chan string)
    go func() {
        for i, _ := range lst {
            ret <- lst[len(lst)-1-i]
        }
        close(ret)
    }()
    return ret
}

func main() {
    elms := []string{"a", "b", "c", "d"}
    for e := range reverse(elms) {
        fmt.Println(e)
    }
}

对我来说,这似乎是一个干净且易于使用的解决方案。是否可以使用类型将其概括[]interface{}?因为现在的reverse-function仅支持字符串。
2015年

可以肯定的是,只需用interface {}替换字符串,就可以使用了。我只想强调一下,带有签名的函数func reverse(lst []interface{}) chan inyterface{} 将不再将[]字符串作为输入。即使可以在interface {}中强制转换字符串,也不能在[] interface {}中强制转换[] string。不幸的是,当前的反向函数是需要大量重写的那种函数。
user983716 2015年

谢谢。我认为那是棋子的丑陋部分-这在某种程度上是不可避免的。谢谢!
Atmocreations

我会实现一个堆栈,而不是这个。
ᐅdevrimbaris

0

当我需要从切片和反向范围中提取元素时,可以使用类似以下代码的内容:

// reverse range
// Go Playground: https://play.golang.org/p/gx6fJIfb7fo
package main

import (
    "fmt"
)

type Elem struct {
    Id   int64
    Name string
}

type Elems []Elem

func main() {
    mySlice := Elems{{Id: 0, Name: "Alice"}, {Id: 1, Name: "Bob"}, {Id: 2, Name: "Carol"}}
    for i, element := range mySlice {
        fmt.Printf("Normal  range: [%v] %+v\n", i, element)
    }

    //mySlice = Elems{}
    //mySlice = Elems{{Id: 0, Name: "Alice"}}
    if last := len(mySlice) - 1; last >= 0 {
        for i, element := last, mySlice[0]; i >= 0; i-- {
            element = mySlice[i]
            fmt.Printf("Reverse range: [%v] %+v\n", i, element)
        }
    } else {
        fmt.Println("mySlice empty")
    }
}

输出:

Normal  range: [0] {Id:0 Name:Alice}
Normal  range: [1] {Id:1 Name:Bob}
Normal  range: [2] {Id:2 Name:Carol}
Reverse range: [2] {Id:2 Name:Carol}
Reverse range: [1] {Id:1 Name:Bob}
Reverse range: [0] {Id:0 Name:Alice}

游乐场:https : //play.golang.org/p/gx6fJIfb7fo

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.