Apakah ada cara untuk mengulangi irisan secara terbalik di Go?


98

Akan lebih mudah untuk mengatakan sesuatu seperti:

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

Jawaban:


146

Tidak ada operator yang nyaman untuk menambahkan ini ke jangkauan satu di tempat. Anda harus melakukan loop menghitung mundur normal:

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

Contoh halaman go yang efektif , tetapi yang ini sebenarnya sedikit lebih bagus dan mendeklarasikan variabel yang lebih sedikit.
Kevin Cantwell

3
IMO Go sangat membutuhkan konstruksi rentang menurun. Tidak memilikinya menyebabkan banyak pekerjaan ekstra, seperti yang dapat kita lihat .... -
Vector

24
Saya tidak akan mengatakan dengan putus asa, itu akan menyenangkan.
Adam Kurkiewicz

47

Anda juga bisa melakukan:

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
}

Keluaran:

1
2
3
4
5

Juga di sini: http://play.golang.org/p/l7Z69TV7Vl


15

Variasi dengan indeks

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

6

Bagaimana jika menggunakan penundaan:

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

9
Saya telah memilih-up hanya karena fakta itu membawa beberapa pengetahuan baru tentang defertetapi saya percaya menggunakan ini di dalam loop untuk mundur cukup rumit dan seharusnya cukup tidak efektif dalam hal memori.
Alexander Trakhimenok

11
Ini "berfungsi", tetapi jika loop bukan hal terakhir dalam fungsi, Anda mungkin mendapatkan hasil yang tidak diharapkan. Contoh.
Daniel

6
Ini digunakan deferdengan cara yang tidak dimaksudkan untuk itu. Jangan gunakan ini karena dapat memiliki efek samping yang buruk (keluar dari urutan eksekusi). Cukup gunakan forloop dalam jawaban yang diterima. Go bertujuan untuk meminimalkan peretasan pintar (bukan) semacam ini karena mereka cenderung menggigit Anda nanti.
RickyA

6
Ini adalah penggunaan penundaan yang hacky dan harus dihindari. Jika ini adalah, misalnya, fungsi yang mungkin dikembangkan seseorang di masa mendatang, ini mungkin memiliki konsekuensi yang tidak diinginkan.
Amir Keibi

6
Ini tidak cukup 'meragukan', jadi saya melanjutkan dan menambahkan saluran play.golang.org/p/GodEiv1LlIJ
Xeoncross

4

Seseorang dapat menggunakan saluran untuk membalik daftar dalam suatu fungsi tanpa menduplikasinya. Itu membuat kode lebih bagus dalam pengertian saya.

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

Itu tampak seperti solusi yang bersih dan bagus untuk digunakan bagi saya. Apakah mungkin untuk menggeneralisasi ini menggunakan tipe []interface{}? Karena reversefungsi sekarang hanya mendukung string.
Atmocreations

Yang pasti, cukup ganti string demi antarmuka {} dan Anda siap melakukannya. Saya hanya ingin menekankan bahwa fungsi dengan tanda tangan func reverse(lst []interface{}) chan inyterface{} tidak akan lagi menggunakan string [] sebagai masukan. Bahkan jika string bisa dicasting dalam antarmuka {}, string [] tidak bisa ditransmisikan dalam antarmuka [] {}. Sayangnya, fungsi kebalikan saat ini adalah jenis fungsi yang perlu banyak ditulis ulang.
pengguna983716

Terima kasih. Itu bagian buruk dari perjalanan saya pikir - yang entah bagaimana tidak dapat dihindari. Terima kasih!
Atmocreations

Saya akan menerapkan tumpukan daripada ini.
ᐅ devrimbaris

0

Ketika saya perlu mengekstrak elemen dari rentang irisan dan terbalik, saya menggunakan sesuatu seperti kode ini:

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

Keluaran:

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}

Taman bermain: https://play.golang.org/p/gx6fJIfb7fo

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.