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

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

Is there a way to iterate over a slice in reverse in Go?

问题

对于能够像这样说的话会很方便:

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

编辑:我很久以前问过这个问题,现在是2022年,@Ivan提供的通用解决方案似乎是正确的方法!

英文:

It would be convenient to be able to say something like:

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

Edit: I asked this question a long time ago, it is 2022 now and the generic solution by @Ivan below seems like the way to go!

答案1

得分: 219

没有方便的运算符可以直接将范围中的一个元素添加到其中。您需要使用普通的for循环进行倒数计数:

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

No there is no convenient operator for this to add to the range one in place. You'll have to do a normal for loop counting down:

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

答案2

得分: 64

你也可以这样做:

s := []int{5, 4, 3, 2, 1}
for i := range s {
        fmt.Println(s[len(s)-1-i]) // 建议:在循环之前执行 `last := len(s)-1`
}

输出:

1
2
3
4
5

还可以在这里查看:http://play.golang.org/p/l7Z69TV7Vl

英文:

You can also do:

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
}

Output:

1
2
3
4
5

Also here: http://play.golang.org/p/l7Z69TV7Vl

答案3

得分: 20

根据索引变化

for k := range s {
		k = len(s) - 1 - k
		// 现在 k 从末尾开始
	}
英文:

Variation with index

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

答案4

得分: 6

如何使用defer:

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

How about use defer:

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

答案5

得分: 5

一个可以使用通道来在函数中反转一个列表而不重复它的方法。这样做可以使代码更加优雅。

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)
	}
}
英文:

One could use a channel to reverse a list in a function without duplicating it. It makes the code nicer in my sense.

package main

import (
	&quot;fmt&quot;
)

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

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

答案6

得分: 5

在2022年,您可以使用泛型来原地反转任何切片:

func reverse[S ~[]E, E any](s S) {
    for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
        s[i], s[j] = s[j], s[i]
    }
}
英文:

In 2022, you could use generics to reverse any slice in-place:

func reverse[S ~[]E, E any](s S) {
	for i, j := 0, len(s)-1; i &lt; j; i, j = i+1, j-1 {
		s[i], s[j] = s[j], s[i]
	}
}

答案7

得分: -2

当我需要从切片中提取元素并反转范围时,我使用类似以下代码的方式:

// 反转范围
// 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("正常范围: [%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("反转范围: [%v] %+v\n", i, element)
        }
    } else {
        fmt.Println("mySlice为空")
    }
}

输出:

正常范围: [0] {Id:0 Name:Alice}
正常范围: [1] {Id:1 Name:Bob}
正常范围: [2] {Id:2 Name:Carol}
反转范围: [2] {Id:2 Name:Carol}
反转范围: [1] {Id:1 Name:Bob}
反转范围: [0] {Id:0 Name:Alice}

Playground: https://play.golang.org/p/gx6fJIfb7fo

英文:

When I need to extract elements from a slice and reverse range, I use something like this code:

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

import (
	&quot;fmt&quot;
)

type Elem struct {
	Id   int64
	Name string
}

type Elems []Elem

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

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

Output:

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}

Playground: https://play.golang.org/p/gx6fJIfb7fo

答案8

得分: -4

你可以使用go-funk中的funk.ForEachRight方法:

results := []int{}

funk.ForEachRight([]int{1, 2, 3, 4}, func(x int) {
    results = append(results, x)
})

fmt.Println(results) // []int{4, 3, 2, 1}
英文:

You can use the funk.ForEachRight method from go-funk:

results := []int{}

funk.ForEachRight([]int{1, 2, 3, 4}, func(x int) {
    results = append(results, x)
})

fmt.Println(results) // []int{4, 3, 2, 1}

huangapple
  • 本文由 发表于 2012年11月2日 15:07:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/13190836.html
匿名

发表评论

匿名网友

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

确定