Goで逆にスライスを反復する方法はありますか?


95

次のようなことが言えると便利です。

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

回答:


139

これを適切な範囲に追加するための便利な演算子はありません。通常のループカウントダウンを行う必要があります。

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

効果的な、外出先ページの例が、これは実際にはビット進歩して、より少ない変数を宣言します。
Kevin Cantwell、

3
IMO Goには、必死に降順の範囲構成が必要です。-私たちが....見ることができるように、それは、余分な作業の良い取引を引き起こし持っていない
ベクトル

24
私は必死に言うつもりはありません、それは素晴らしい所でしょう。
Adam Kurkiewicz、2014年

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



6

延期の使用はどうですか:

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

8
私はそれがいくつかの新しい知識をもたらしたという事実だけに賛成票を投じましたdeferが、これを逆方向のループ内で使用することは非常にトリッキーであり、メモリの点でかなり効果がないはずです。
Alexander Trakhimenok 2016年

10
これは「機能します」が、ループが関数の最後のものでない場合は、予期しない結果が生じる可能性があります。例。
ダニエル

5
これはdefer意図されていない方法で使用しています。これは厄介な副作用(順不同の実行)を引き起こす可能性があるため、使用しないでください。for受け入れられた回答でループを使用するだけです。Goは、このような巧妙な(ではない)ハックを最小限に抑えることを目的としています。
RickyA

4
これは遅延のハックな使い方であり、回避する必要があります。これが、たとえば、将来誰かが拡張する可能性がある機能である場合、意図しない結果が生じる可能性があります。
Amir Keibi 2016

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関数は文字列のみをサポートしているためです。
2015年

確かに、文字列をインターフェース{}に置き換えるだけで、問題ありません。シグネチャのある関数func reverse(lst []interface{}) chan inyterface{} は[]文字列を入力として使用しないことを強調したいだけです。文字列をインターフェイス{}でキャストできる場合でも、[]文字列を[]インターフェイス{}でキャストすることはできません。残念ながら、現在の逆関数は、多くの書き換えが必要な種類の関数です。
user983716

ありがとうございました。これは私が思うに醜い部分です。これはどういうわけか避けられないことです。ありがとうございました!
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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.