Dilimdeki eleman konumunu nasıl öğrenebilirim?


108

Dilimde bulunan bir elemanın konumu nasıl belirlenir?

Aşağıdaki gibi bir şeye ihtiyacım var:

type intSlice []int

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

2
peki, soru nedir? kod çalışmıyor mu?
newacct

8
Neden go kodlayıcılar bu kadar ortak işlevleri kendi başlarına yazsınlar diye soruyordum. Demek istediğim, float değerleri için başka bir işlev istersem, bu işlevi kopyalamaya / yapıştırmaya zorlanacağım. Bu bana garip geldi. Ancak Krzysztof Kowalczyk zaten cevabını verdi, çünkü golang'ın jenerik ilaçları yok.
OCyril

Dilimin sıralandı mı?
dolmen

Yanıtlar:


70

Üzgünüz, bunu yapacak genel bir kitaplık işlevi yok. Go, herhangi bir dilim üzerinde çalışabilen bir işlev yazmak için basit bir yola sahip değildir.

Fonksiyonunuz çalışır, ancak onu kullanarak yazarsanız biraz daha iyi olur range.

Bir bayt diliminiz varsa, baytlar vardır.IndexByte .


3
Evan'a katılıyorum. Ek yorum: -1'in "bulunamadı" (bytes.IndexByte gibi) gösterdiği bir int döndürmek daha deyimseldir
Krzysztof Kowalczyk

2
Teşekkürler. Ama biraz bunaldım :) Golang kullanan insanlardan defalarca duydum, programcı verimliliğini artırmak için çok iyi tasarlandı. Ve go programları python programları kadar güzel görünüyor :) Öyleyse neden bu kadar yaygın bir görevi yapmanın ortak bir yolu yok? Demek istediğim, eğer kabın bir eleman if element in collection: do_something()
içerip içermediğini

10
Teknik cevap şu: çünkü Go'nun jenerikleri yok. Eğer öyleyse (ve belki gelecekte bir noktada onlara sahip olacaktır), == uygulayan her tür üzerinde çalışan genel bir IndexInSlice yazabilirdiniz. Go savunucu şapkamı koymak: ortalama bir deneyimle ilgili. Tek bir dilin diğer tüm dilleri her yönüyle yenmesini bekleyemezsiniz. Go , C, C ++, hatta Java veya C # 'dan çok daha üretken ve python'a yakın. Programcı üretkenliği ile yerel kod üretiminin (yani hızın) birleşimi onu çekici kılıyor.
Krzysztof Kowalczyk

1
Diğer bir seçenek, genel işlevlerin oluşturulması için daha yüksek dereceli işlevleri ve kapanmaları kullanmaktır. Bir örnekle cevap ekledim.
Hoca,

1
@OCyril Kendi jeneriklerinizi yazmalı ve kendi kütüphanenizi oluşturmalı veya araştırma yapmalı ve ihtiyaçlarınıza uygun bir şey bulmalısınız. En düşük seviyede, 'dizide x değeri bul' fonksiyonu (PHP, Python veya her neyse) OP'nin sorusunda verilen versiyona - düşük seviyede - benzeyecektir. Döngüler, gizli olsalar bile bu tür programlamanın merkezidir. Git bu şeyleri saklamaz.
Ian Lewis

54

Deyimsel go yolunda genel işlev oluşturabilirsiniz:

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

Ve kullanım:

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
Bunu seviyorum, ama bu şekilde düşünmekte zorlanıyorum
Decebal

1
-1Bir hata için geri dönmenin deyimsel olduğunu düşünmüyorum , bunun yerine çoklu dönüş kullanmalı. (Golang'da yeniyim ama okuduğum şey bu)
Tim Abell

7
Hareket halindeyken derleme dizini işlevleri her zaman -1 döndürür. Bu beklenen deyimsel bir davranıştır. Eksik eleman bir hata değildir.
Hodza

Bu fantastik! Çok kullanışlı :) Teşekkürler!
Gaurav Ojha

12

Bir fonksiyon yazabilirsiniz;

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

Bu, öğeyle eşleşirse bir karakter / dizenin dizinini döndürür. Bulunmazsa, -1 döndürür.


6

Bunun için kütüphane işlevi yoktur. Kendi başınıza kodlamalısınız.


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

1

Diğer bir seçenek de dilimi sıralama paketini kullanarak sıralamak ve ardından aradığınız şeyi aramaktır:

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

baskılar

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

Bu, temel türler için işe yarar ve bir dilim başka şeyler üzerinde çalışmanız gerekirse, kendi türünüz için sıralama arabirimini her zaman uygulayabilirsiniz. Bkz. Http://golang.org/pkg/sort

Yine de ne yaptığına bağlı.


Tamam teşekkürler. Ancak, yalnızca dilimde belirli bir öğe olup olmadığını kontrol etmek istersem, bunu kullanmak tuhaf görünüyor :)
OCyril

3
bu orijinal dizini bulamaz; bunun yerine tüm dizinleri yeniden
sıralayarak

Elbette, bu yüzden kullanıma bağlı. Bu sadece bir çekse, o zaman elbette, sadece for p, v := range ...ve kullanın if. Sadece seçeneği belirtmek istedim.
robothor
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.