Go'da bir dilimi tersine yinelemenin bir yolu var mı?


98

Şöyle bir şey söyleyebilmek uygun olacaktır:

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

Yanıtlar:


146

Yerinde bir aralığa eklemek için bunun için uygun bir operatör yoktur. Geri sayım için normal bir for döngüsü yapmanız gerekecek:

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

Etkili go sayfa bir örnek, ama bu aslında biraz daha güzel ve daha az değişken bildirir.
— Kevin Cantwell

3
IMO Go'nun azalan bir aralık yapısına umutsuzca ihtiyacı var. Gördüğümüz gibi, buna sahip olmamak çok fazla ekstra çalışmaya neden olur .... -
— Vektör

24
Umutsuzca demezdim, güzel bir sahip olur.
— Adam Kurkiewicz

47

Ayrıca şunları da yapabilirsiniz:

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
}

Çıktı:

1
2
3
4
5

Ayrıca burada: http://play.golang.org/p/l7Z69TV7Vl


15

Endeksli varyasyon

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

6

Ertelemeye ne dersiniz:

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

9
Sadece bazı yeni bilgiler getirdiği için yukarı oy verdim, deferancak bunu bir döngü içinde tersine çevirmek için kullanmanın oldukça zor olduğuna ve hafıza açısından oldukça etkisiz olması gerektiğine inanıyorum.
— Alexander Trakhimenok

11
"Çalışır", ancak döngü işlevdeki son şey değilse, beklenmedik sonuçlar alabilirsiniz. Misal.
— Daniel

6
Bu, deferamaçlanmayan bir şekilde kullanılıyor . Kötü yan etkileri olabileceğinden bunu kullanmayın (sıra dışı uygulama). Sadece forkabul edilen cevapta döngüyü kullanın . Go, daha sonra sizi kıçınıza sokma eğiliminde olduklarından , bu tür zekice (değil) saldırıları en aza indirmeyi amaçlamaktadır .
— RickyA

6
Bu, ertelemenin karmaşık bir kullanımıdır ve bundan kaçınılmalıdır. Örneğin bu, birisinin gelecekte genişletebileceği bir işlevse, istenmeyen sonuçları olabilir.
— Amir Keibi

6
Devam ettim ve böylece bu, oldukça 'şüpheli' yeterli değildi eklenen kanallar play.golang.org/p/GodEiv1LlIJ
— Xeoncross

4

Bir işlevdeki bir listeyi çoğaltmadan ters çevirmek için bir kanal kullanılabilir. Bence kodu daha güzel yapıyor.

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

Bu bana temiz ve kullanımı güzel bir çözüm gibi görünüyor. Bunu türü kullanarak genellemek mümkün mü []interface{}? Çünkü şimdiki reverseişlevi yalnızca dizeleri destekler.
— Atmocreations

Elbette, dizeyi arayüzle {} değiştirin ve hazırsınız. İmzalı bir işlevin func reverse(lst []interface{}) chan inyterface{} artık girdi olarak bir [] dizesi almayacağını vurgulamak istiyorum . {} Arayüzünde dizge dönüştürülebilir olsa bile, [] dizesi [] arabirim {} içinde dönüştürülemez. Ne yazık ki, şimdiki ters işlev, çok fazla yeniden yazılması gereken işlev türüdür.
— user983716

Teşekkür ederim. Bence gitmenin çirkin kısmı bu - ki bu bir şekilde kaçınılmaz. Teşekkür ederim!
— Atmocreations

Bunun yerine bir yığın uygulardım.
— ᐅ devrimbaris

0

Bir dilimden ve ters aralıktan öğeler çıkarmam gerektiğinde, şu kod gibi bir şey kullanıyorum:

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

Çıktı:

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}

Oyun alanı: https://play.golang.org/p/gx6fJIfb7fo

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.