スライス内の要素の位置を見つける方法は?


108

スライスに存在する要素の位置をどのように決定しますか?

次のようなものが必要です。

type intSlice []int

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

2
それで、質問は何ですか?コードは機能しませんか?
newacct

8
なぜプログラマーがそのような一般的な関数を自分で書くべきなのかと尋ねていました。つまり、float値用の別の関数が必要な場合は、この関数をコピー/貼り付けする必要があります。これは私には奇妙に見えました。しかし、Krzysztof Kowalczykは、golangにジェネリックがないためであると既に回答しています。
OCyril、2011年

スライスは分類されていますか?
ドルメン、

2
このソースを試してください:gobyexample.com/collection-functions
Victor

回答:


70

申し訳ありませんが、これを行うための汎用ライブラリ関数はありません。Goには、任意のスライスを操作できる関数を簡単に作成する方法がありません。

関数は機能しますが、を使用して記述した方が少し良いでしょうrange

たまたまバイトスライスがある場合は、bytes.IndexByteがあります


3
私はエヴァンに同意します。追加コメント:-1が「見つからない」ことを示すint(bytes.IndexByteなど)のみを返す方がより慣用的です
Krzysztof Kowalczyk

2
ありがとう。しかし、私は少し圧倒されています:)プログラマーの生産性を向上させるために非常によく設計されているとgolangを使用している人々から何度も聞いたことがあります。goプログラムはpythonのプログラムと同じくらい美しく見えます:)では、なぜこのような一般的なタスクを実行する一般的な方法がないのでしょうか。あなたは、コンテナは、あなただけできる要素があるかどうかを確認したい場合、私は、意味if element in collection: do_something()
OCyril

10
技術的な答えは、Goにはジェネリックがないためです。もしそうなら(そしておそらく将来的にはそれらが含まれるようになるでしょう)、==を実装する任意の型で機能する汎用のIndexInSliceを書くことができます。私の囲碁提唱者の帽子をかぶる:それは平均的な経験についてです。1つの言語があらゆる面で他のすべての言語に勝ることを期待することはできません。Go 、C、C ++よりもはるかに生産性が高く、おそらくJavaやC#でさえ、Pythonに近いです。魅力的なのは、プログラマーの生産性とネイティブコード生成(つまり速度)の組み合わせです。
Krzysztof Kowalczyk 2011年

1
別のオプションは、ジェネリック関数の作成に高次関数とクロージャーを使用することです。例を挙げて回答を追加しました。
Hodza 2013

1
@OCyril独自のジェネリックを作成して独自のライブラリを構築するか、調査を行ってニーズに合ったものを見つける必要があります。最下位レベルでは、「find value = x in array」関数(PHP、Pythonなど)は、OPの質問で指定されたバージョンにいくらか似ています(低レベル)。ループは、たとえ隠されていても、この種のプログラミングの中心です。Goはこのアイテムを非表示にしません。
イアンルイス

54

一般的な関数を慣用的な方法で作成できます。

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

そして使い方:

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
これは大好きですが、このように考えるのは難しいと思います
Decebal

1
-1エラーの戻りは慣用的ではないと思います。代わりに複数の戻りを使用する必要があります。(golangは初めてですが、それは私が読んだ内容です)
Tim Abell、

7
goのBuildtinインデックス関数は常に-1を返します。これは予想される慣用的な動作です。欠落している要素はエラーではありません。
Hodza

これは素晴らしいです!とても便利です:)ありがとう!
Gaurav Ojha 2017年

12

関数を書くことができます。

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

要素と一致する場合、文字/文字列のインデックスを返します。見つからない場合は、-1を返します。



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

1

別のオプションは、sortパッケージを使用してスライスをソートしてから、探しているものを検索することです。

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

プリント

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

これは基本的なタイプで機能し、他のもののスライスで作業する必要がある場合は、いつでも独自のタイプのソートインターフェイスを実装できます。http://golang.org/pkg/sortを参照してください

あなたが何をしているかにもよる。


わかりました。しかし、スライスに特定の要素が含まれているかどうかを確認したいだけの場合、これを使用するのは奇妙に思えます:)
OCyril

3
これは元のインデックスを見つけません。むしろ、インデックスを
並べ替える

確かに、それはそれが使用法に依存する理由です。単なるチェックの場合は、とを使用for p, v := range ...してくださいif。オプションを指摘したかっただけです。
robothor
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.