Bagaimana cara mengetahui posisi elemen dalam slice?


108

Bagaimana cara menentukan posisi elemen yang ada dalam potongan?

Saya butuh sesuatu seperti berikut:

type intSlice []int

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

2
jadi apa pertanyaannya? apakah kodenya tidak berfungsi?
newacct

8
Saya bertanya mengapa go coders harus menulis fungsi umum seperti itu sendiri? Maksud saya, jika saya menginginkan fungsi lain untuk nilai float, saya akan dipaksa untuk menyalin / menempel fungsi ini. Ini tampak aneh bagiku. Tapi Krzysztof Kowalczyk sudah menjawab, itu karena golang tidak punya obat generik.
OCyril

Apakah potongan Anda sudah diurutkan?
dolmen

Jawaban:


70

Maaf, tidak ada fungsi perpustakaan umum untuk melakukan ini. Go tidak memiliki cara langsung untuk menulis fungsi yang dapat beroperasi pada slice apa pun.

Fungsi Anda berfungsi, meskipun akan sedikit lebih baik jika Anda menulisnya menggunakan range.

Jika Anda kebetulan memiliki potongan byte, ada byte.IndexByte .


3
Saya setuju dengan Evan. Komentar tambahan: lebih idiomatis mengembalikan hanya int di mana -1 menunjukkan "tidak ditemukan" (seperti bytes.IndexByte)
Krzysztof Kowalczyk

2
Terima kasih. Tapi saya sedikit kewalahan :) Saya sering mendengar dari orang-orang yang menggunakan golang, bahwa itu dirancang dengan sangat baik untuk meningkatkan produktivitas programmer. Dan program go terlihat bagus seperti python :) Jadi mengapa tidak ada cara umum untuk melakukan tugas umum seperti itu? Maksud saya, jika Anda ingin memeriksa apakah wadah memiliki elemen Anda bisaif element in collection: do_something()
OCyril

10
Jawaban teknisnya adalah: karena Go tidak memiliki obat generik. Jika ya (dan mungkin di beberapa titik di masa depan akan memilikinya) Anda bisa menulis IndexInSlice generik yang bekerja pada semua jenis yang mengimplementasikan ==. Menempatkan topi pendukung Go saya: ini tentang pengalaman rata-rata. Anda tidak dapat mengharapkan satu bahasa mengalahkan setiap bahasa lainnya dalam setiap aspek. Go adalah jauh lebih produktif daripada C, C ++, bahkan mungkin Java atau C # dan dekat dengan python. Ini adalah kombinasi dari produktivitas programmer dan pembuatan kode asli (yaitu kecepatan) yang membuatnya menarik.
Krzysztof Kowalczyk

1
Pilihan lainnya adalah menggunakan fungsi dan closure orde tinggi untuk pembuatan fungsi generik. Saya menambahkan jawaban dengan sebuah contoh.
Hodza

1
@OCyril Anda harus menulis obat generik Anda sendiri dan membangun perpustakaan Anda sendiri atau melakukan penelitian dan menemukan sesuatu yang sesuai dengan kebutuhan Anda. Pada level terendah, fungsi 'find value = x in array' (PHP, Python, atau apa pun) akan terlihat seperti versi yang diberikan dalam pertanyaan OP - pada level rendah. Pengulangan adalah pusat dari jenis pemrograman ini, meskipun mereka tersembunyi. Go tidak menyembunyikan barang ini.
Ian Lewis

54

Anda dapat membuat fungsi generik dengan cara idiomatic go:

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

Dan penggunaan:

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
Suka ini, tetapi saya merasa sulit untuk memikirkannya seperti ini
Desebal

1
Saya tidak berpikir mengembalikan -1kesalahan itu idiomatis, seharusnya menggunakan pengembalian ganda sebagai gantinya. (Saya baru mengenal golang tapi itulah yang saya baca)
Tim Abell

7
Fungsi indeks buildtin dalam menjalankan selalu mengembalikan -1. Ini adalah perilaku idiomatik yang diharapkan. Elemen yang hilang bukanlah kesalahan.
Hodza

Ini fantastis! Sangat berguna :) Terima kasih!
Gaurav Ojha

12

Anda bisa menulis sebuah fungsi;

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

Ini mengembalikan indeks karakter / string jika cocok dengan elemen. Jika tidak ditemukan, mengembalikan -1.



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

1

Opsi lainnya adalah mengurutkan potongan menggunakan paket sortir, lalu cari hal yang Anda cari:

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

cetakan

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

Ini berfungsi untuk tipe dasar dan Anda selalu dapat mengimplementasikan antarmuka sortir untuk tipe Anda sendiri jika Anda perlu mengerjakan sepotong hal lain. Lihat http://golang.org/pkg/sort

Tergantung pada apa yang Anda lakukan.


Ok terima kasih. Tapi saya rasa itu terlihat aneh menggunakan ini jika saya hanya ingin memeriksa apakah irisan mengandung elemen yang diberikan :)
OCyril

3
ini tidak menemukan indeks asli; melainkan kehilangan semua indeks dengan memesan ulang mereka
newacct

Tentu, itu sebabnya tergantung dari penggunaannya. Jika itu hanya sebuah cek, maka pasti, gunakan saja for p, v := range ...dan if. Hanya ingin menunjukkan opsi.
robothor
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.