Có cách nào để lặp lại một lát trong cờ vây không?


98

Sẽ rất tiện lợi nếu có thể nói những điều như:

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

Câu trả lời:


145

Không có toán tử nào thuận tiện cho việc này để thêm vào phạm vi một tại chỗ. Bạn sẽ phải thực hiện bình thường cho vòng lặp đếm ngược:

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

Các hiệu quả đi trang một ví dụ, nhưng điều này thực sự là một chút đẹp hơn và tuyên bố biến ít hơn.
Kevin Cantwell

3
IMO Go rất cần một cấu trúc phạm vi giảm dần. Không có nó sẽ gây ra rất nhiều việc làm thêm, như chúng ta có thể thấy .... -
Véc tơ vào

24
Tôi sẽ không nói một cách tuyệt vọng, nó sẽ là một điều tuyệt vời.
Adam Kurkiewicz

47

Bạn cũng có thể làm:

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
}

Đầu ra:

1
2
3
4
5

Cũng tại đây: http://play.golang.org/p/l7Z69TV7Vl


15

Biến thể với chỉ mục

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

6

Làm thế nào về việc trì hoãn sử dụng:

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

9
Tôi đã bỏ phiếu chỉ vì thực tế là nó mang lại một số kiến ​​thức mới defernhưng tôi tin rằng việc sử dụng điều này bên trong một vòng lặp để đảo ngược là khá phức tạp và sẽ khá kém hiệu quả về trí nhớ.
Alexander Trakhimenok

11
Nó "hoạt động", nhưng nếu vòng lặp không phải là điều cuối cùng trong hàm, bạn có thể nhận được kết quả không mong muốn. Thí dụ.
Daniel

6
Điều này đang sử dụng defertheo cách mà nó không được dự định. Không sử dụng điều này vì nó có thể có các tác dụng phụ khó chịu (thực hiện không theo thứ tự). Chỉ cần sử dụng forvòng lặp trong câu trả lời được chấp nhận. Go nhằm mục đích giảm thiểu loại hack thông minh (không phải) này vì chúng có xu hướng cắn bạn vào mông sau này.
RickyA

6
Đây là cách sử dụng trì hoãn gian lận và nên tránh. Ví dụ: nếu đây là một chức năng mà ai đó có thể mở rộng trong tương lai, thì nó có thể gây ra những hậu quả không mong muốn.
Amir Keibi

6
Điều này vẫn chưa đủ 'iffy', vì vậy tôi đã tiếp tục và thêm kênh play.golang.org/p/GodEiv1LlIJ
Xeoncross vào

4

Người ta có thể sử dụng một kênh để đảo ngược danh sách trong một hàm mà không cần sao chép nó. Nó làm cho mã đẹp hơn theo cảm nhận của tôi.

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

Đó có vẻ như là một giải pháp sạch sẽ và dễ sử dụng đối với tôi. Có thể tổng quát điều này bằng cách sử dụng loại []interface{}? Bởi vì reversechức năng hiện tại chỉ hỗ trợ chuỗi.
Atmocreations

Chắc chắn, chỉ cần thay thế chuỗi bằng giao diện {} và bạn có thể bắt đầu. Tôi chỉ muốn nhấn mạnh rằng một hàm có chữ ký func reverse(lst []interface{}) chan inyterface{} sẽ không lấy chuỗi [] làm đầu vào nữa. Ngay cả khi chuỗi có thể được truyền trong giao diện {}, chuỗi [] không thể được truyền trong [] giao diện {}. Thật không may, hàm đảo ngược hiện tại là loại hàm cần được viết lại rất nhiều.
user983716

Cảm ơn bạn. Tôi nghĩ đó là phần xấu xí của việc đi - điều này là không thể tránh khỏi. Cảm ơn bạn!
Atmocreations

Tôi sẽ thực hiện một ngăn xếp hơn là điều này.
ᐅ devrimbaris

0

Khi tôi cần trích xuất các phần tử từ một lát cắt và phạm vi đảo ngược, tôi sử dụng một cái gì đó giống như mã này:

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

Đầu ra:

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}

Sân chơi: https://play.golang.org/p/gx6fJIfb7fo

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.