Apakah ada cara untuk mengulangi irisan secara terbalik di Go?

98

Akan lebih mudah untuk mengatakan sesuatu seperti:

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

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])
}
Ulf Holm Nielsen
sumber
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

zzzz
sumber
15

Variasi dengan indeks

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

Bagaimana jika menggunakan penundaan:

s := []int{5, 4, 3, 2, 1}
for i, _ := range s {
   defer fmt.Println(s[i])
}
Matt
sumber
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)
    }
}
pengguna983716
sumber
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

Vladimir Filin
sumber