5

スライスの値を見つける関数を書きたいとしましょう

私は直感的に書きたい:

func find(s []interface{}, f func(interface{})bool) int {
    for i, item := range s {
        if f(item) {
            return i
        }
    }
    return -1
}

ただし、Goでこれを行うことはできません。私はとのインターフェースを持つことができました

Len() int
Value(int) interface{}
...

これは機能しますが、実際のコードではより複雑です (スライス [from:end] などを実行する必要があります)、追加、... などであり、インターフェイスでこれらすべてを再定義すると、多くのコードが作成されます。 . より良い方法はありますか?

4

3 に答える 3

5

反射を使用できます。プロジェクト用にこの関数を作成しました。自由に使用してください。

// InSlice returns true if value is in slice
func InSlice(value, slice interface{}) bool {
    switch reflect.TypeOf(slice).Kind() {
    case reflect.Slice, reflect.Ptr:
        values := reflect.Indirect(reflect.ValueOf(slice))
        if values.Len() == 0 {
            return false
        }

        val := reflect.Indirect(reflect.ValueOf(value))

        if val.Kind() != values.Index(0).Kind() {
            return false
        }

        for i := 0; i < values.Len(); i++ {
            if reflect.DeepEqual(values.Index(i).Interface(), val.Interface()) {
                return true
            }
        }
    }
    return false
}
于 2016-07-22T12:16:46.523 に答える
1

[]intorのような定義済みの型があり、変換してこの動作サンプル コードを表示[]stringしたくない場合 ( を使用せずに): []interface{}reflect

package main

import "fmt"

func find(s []int, f func(int) bool) int {
    for i, item := range s {
        if f(item) {
            return i
        }
    }
    return -1
}
func findString(s []string, f func(string) bool) int {
    for i, item := range s {
        if f(item) {
            return i
        }
    }
    return -1
}

func main() {
    s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    fmt.Println(find(s, func(a int) bool { return a == 5 })) //5

    strs := []string{"A", "B", "C"}
    fmt.Println(findString(strs, func(a string) bool { return a == "B" })) //1
}

またはreflect、次の作業サンプル コードのように 使用することもできます。

package main

import "fmt"
import "reflect"

func find(slice interface{}, f func(interface{}) bool) int {
    switch reflect.TypeOf(slice).Kind() {
    case reflect.Slice:
        values := reflect.Indirect(reflect.ValueOf(slice))
        for i := 0; i < values.Len(); i++ {
            if f(values.Index(i).Interface()) {
                return i
            }
        }
    }
    return -1
}

func main() {
    a := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    fmt.Println(find(a, func(i interface{}) bool { return i == 5 })) //5

    b := []string{"A", "B", "C"}
    fmt.Println(find(b, func(i interface{}) bool { return i == "B" })) //1
}

出力:

5
1

これが役立つことを願っています。

于 2016-07-22T12:11:45.507 に答える
0

任意の値のスライスを持ち、そのようなfind関数を使用し、標準の[]再スライスの可能性がある場合、おそらく最良の方法はinterface{}、別の構造体でカプセル化することです

type proxy struct {
    val interface{}
}

と使用

func find(s []proxy , f func(proxy)bool) int {}

f関数でinterface{}比較/型キャストを処理します。

于 2016-07-22T12:39:13.943 に答える