Làm thế nào để tìm ra vị trí của phần tử trong lát cắt?


108

Làm thế nào để xác định vị trí của một phần tử hiện diện trong lát cắt?

Tôi cần một cái gì đó như sau:

type intSlice []int

func (slice intSlice) pos(value int) int {
    for p, v := range slice {
        if (v == value) {
            return p
        }
    }
    return -1
}

2
vậy, câu hỏi là gì? mã không hoạt động?
newacct

8
Tôi đã hỏi tại sao các lập trình viên phải tự viết các hàm phổ biến như vậy? Ý tôi là nếu tôi muốn một hàm khác cho các giá trị float, tôi sẽ buộc phải sao chép / dán hàm này. Điều này trông kỳ lạ đối với tôi. Nhưng Krzysztof Kowalczyk đã trả lời rằng đó là vì golang không có generic.
OCyril

Lát của bạn có được sắp xếp không?
dolmen

2
Hãy thử nguồn này: gobyexample.com/collection-functions
Victor

Câu trả lời:


70

Xin lỗi, không có chức năng thư viện chung nào để làm điều này. Go không có cách viết thẳng về một hàm có thể hoạt động trên bất kỳ lát cắt nào.

Hàm của bạn hoạt động, mặc dù nó sẽ tốt hơn một chút nếu bạn viết nó bằng cách sử dụng range.

Nếu bạn tình cờ có một lát byte, sẽ có byte.IndexByte .


3
Tôi đồng ý với Evan. Bình luận thêm: đó là thành ngữ hơn để trở lại chỉ là một int nơi -1 chỉ "không tìm thấy" (như bytes.IndexByte)
Krzysztof Kowalczyk

2
Cảm ơn. Nhưng tôi hơi bị choáng ngợp :) Tôi đã nghe nhiều lần từ những người sử dụng golang, rằng nó được thiết kế rất tốt để tăng năng suất của lập trình viên. Và các chương trình go trông đẹp như những chương trình python :) Vậy tại sao không có một cách chung nào để thực hiện một tác vụ phổ biến như vậy? Ý tôi là, nếu bạn muốn kiểm tra xem vùng chứa có một phần tử hay không, bạn có thể chỉ cầnif element in collection: do_something()
OCyril

10
Câu trả lời kỹ thuật là: bởi vì cờ vây không có thuốc tổng quát. Nếu nó đã làm (và có thể một lúc nào đó trong tương lai nó sẽ có chúng), bạn có thể đã viết một IndexInSlice chung hoạt động trên bất kỳ kiểu nào triển khai ==. Đặt chiếc mũ ủng hộ cờ vây của tôi: đó là một trải nghiệm trung bình. Bạn không thể mong đợi một ngôn ngữ duy nhất đánh bại mọi ngôn ngữ khác ở mọi khía cạnh. Go nhiều hơn nữa năng suất cao hơn so với C, C ++, thậm chí có Java hay C # và gần gũi với trăn. Đó là sự kết hợp giữa năng suất của lập trình viên và tạo mã gốc (tức là tốc độ) làm cho nó trở nên hấp dẫn.
Krzysztof Kowalczyk

1
Một tùy chọn khác là sử dụng các hàm bậc cao hơn và các hàm đóng để tạo các hàm chung. Tôi đã thêm câu trả lời với một ví dụ.
Hodza

1
@OCyril Bạn phải viết generic của riêng mình và xây dựng thư viện của riêng bạn hoặc thực hiện nghiên cứu và tìm thứ gì đó phù hợp với nhu cầu của bạn. Ở mức thấp nhất, hàm 'find value = x in array' (PHP, Python hoặc bất cứ thứ gì) sẽ trông giống phiên bản được đưa ra trong câu hỏi của OP - ở mức thấp. Vòng lặp là trọng tâm của kiểu lập trình này, ngay cả khi chúng bị ẩn. Đi không giấu công cụ này.
Ian Lewis

54

Bạn có thể tạo hàm chung theo cách đi thành ngữ:

func SliceIndex(limit int, predicate func(i int) bool) int {
    for i := 0; i < limit; i++ {
        if predicate(i) {
            return i
        }
    }
    return -1
}

Và cách sử dụng:

xs := []int{2, 4, 6, 8}
ys := []string{"C", "B", "K", "A"}
fmt.Println(
    SliceIndex(len(xs), func(i int) bool { return xs[i] == 5 }),
    SliceIndex(len(xs), func(i int) bool { return xs[i] == 6 }),
    SliceIndex(len(ys), func(i int) bool { return ys[i] == "Z" }),
    SliceIndex(len(ys), func(i int) bool { return ys[i] == "A" }))

1
Tình yêu này, nhưng tôi thấy nó khó có thể đi để suy nghĩ về nó theo cách này
Decebal

1
Tôi không nghĩ việc trả lại -1lỗi là một câu thành ngữ, thay vào đó, nó nên sử dụng nhiều lần trả lại. (Tôi mới đến golang nhưng đó là những gì tôi đã đọc)
Tim Abell

7
Các funcs trong chỉ mục Buildtin luôn trả về -1. Đây là hành vi thành ngữ được mong đợi. Thiếu phần tử không phải là một lỗi.
Hodza

Cái này thật tuyệt! Rất hữu ích :) Cảm ơn!
Gaurav Ojha

12

Bạn có thể viết một hàm;

func indexOf(element string, data []string) (int) {
   for k, v := range data {
       if element == v {
           return k
       }
   }
   return -1    //not found.
}

Điều này trả về chỉ mục của một ký tự / chuỗi nếu nó khớp với phần tử. Nếu không tìm thấy, trả về -1.


6

Không có chức năng thư viện cho điều đó. Bạn phải tự viết mã.


2
func index(slice []string, item string) int {
    for i, _ := range slice {
        if slice[i] == item {
            return i
        }
    }
    return -1
}

1

Một tùy chọn khác là sắp xếp lát cắt bằng cách sử dụng gói sắp xếp, sau đó tìm kiếm thứ bạn đang tìm kiếm:

package main

import (
    "sort"
    "log"
    )

var ints = [...]int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}

func main() {
        data := ints
        a := sort.IntSlice(data[0:])
        sort.Sort(a)
        pos := sort.SearchInts(a, -784)
        log.Println("Sorted: ", a)
        log.Println("Found at index ", pos)
}

bản in

2009/11/10 23:00:00 Sorted:  [-5467984 -784 0 0 42 59 74 238 905 959 7586 7586 9845]
2009/11/10 23:00:00 Found at index  1

Điều này hoạt động cho các kiểu cơ bản và bạn luôn có thể triển khai giao diện sắp xếp cho kiểu của riêng mình nếu bạn cần làm việc trên một phần của những thứ khác. Xem http://golang.org/pkg/sort

Phụ thuộc vào những gì bạn đang làm mặc dù.


Được rồi cảm ơn. Nhưng tôi đoán có vẻ lạ sử dụng điều này nếu tôi chỉ muốn kiểm tra xem lát chứa nguyên tố :)
OCyril

3
điều này không tìm thấy chỉ mục gốc; thay vào đó, nó mất tất cả các chỉ mục bằng cách sắp xếp lại chúng
newacct

Chắc chắn, đó là lý do tại sao nó phụ thuộc vào cách sử dụng. Nếu nó chỉ là một kiểm tra, sau đó chắc chắn, chỉ cần sử dụng for p, v := range ...if. Chỉ muốn chỉ ra tùy chọn.
robothor vào
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.