Zawiera metodę na plasterek

Czy jest coś podobnego do metody slice.contains(object) W Go bez konieczności przeszukiwania każdego elementu w kawałku?

 255
Author: vosmith, 2012-05-07

15 answers

Mostafa już zauważył, że taka metoda jest trywialna w zapisie, a mkb dał Ci podpowiedź, aby użyć wyszukiwania binarnego z pakietu sort. Ale jeśli masz zamiar zrobić wiele takich kontroli, można również rozważyć użycie mapy zamiast.

Sprawdzenie, czy dany klucz mapy istnieje, jest trywialne, używając idiomu value, ok := yourmap[key]. Ponieważ nie jesteś zainteresowany wartością, możesz również utworzyć na przykład map[string]struct{}. Użycie pustego struct{} tutaj ma tę zaletę, że nie wymaga żadnych dodatkowy typ mapy wewnętrznej spacji i Go jest zoptymalizowany dla tego rodzaju wartości. Dlatego map[string] struct{} jest popularnym wyborem dla zestawów w świecie Go.

 256
Author: tux21b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-07 17:14:15

Nie, taka metoda nie istnieje, ale jest trywialna do napisania:

func contains(s []int, e int) bool {
    for _, a := range s {
        if a == e {
            return true
        }
    }
    return false
}

Możesz użyć mapy, jeśli to wyszukiwanie jest ważną częścią kodu, ale mapy też kosztują.

 212
Author: Mostafa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-16 17:16:49

Jeśli kawałek jest posortowany, w sort pakiecie zaimplementowane jest wyszukiwanie binarne.

 16
Author: mkb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-07 16:40:19

Zamiast używać slice, map może to lepsze rozwiązanie.

Prosty przykład:

package main

import "fmt"


func contains(slice []string, item string) bool {
    set := make(map[string]struct{}, len(slice))
    for _, s := range slice {
        set[s] = struct{}{}
    }

    _, ok := set[item] 
    return ok
}

func main() {

    s := []string{"a", "b"}
    s1 := "a"
    fmt.Println(contains(s, s1))

}

Http://play.golang.org/p/CEG6cu4JTf

 15
Author: holys,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-03 12:45:04

Pakietsort zawiera elementy składowe, jeśli twój kawałek jest posortowany lub chcesz go posortować.

input := []string{"bird", "apple", "ocean", "fork", "anchor"}
sort.Strings(input)

fmt.Println(contains(input, "apple")) // true
fmt.Println(contains(input, "grow"))  // false

...

func contains(s []string, searchterm string) bool {
    i := sort.SearchStrings(s, searchterm)
    return i < len(s) && s[i] == searchterm
}

SearchString obiecuje zwrócić the index to insert x if x is not present (it could be len(a)), więc sprawdzenie tego ujawnia, czy łańcuch zawiera posortowany kawałek.

 14
Author: Henrik Aasted Sørensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-22 15:45:57
func Contain(target interface{}, list interface{}) (bool, int) {
    if reflect.TypeOf(list).Kind() == reflect.Slice || reflect.TypeOf(list).Kind() == reflect.Array {
        listvalue := reflect.ValueOf(list)
        for i := 0; i < listvalue.Len(); i++ {
            if target == listvalue.Index(i).Interface() {
                return true, i
            }
        }
    }
    if reflect.TypeOf(target).Kind() == reflect.String && reflect.TypeOf(list).Kind() == reflect.String {
        return strings.Contains(list.(string), target.(string)), strings.Index(list.(string), target.(string))
    }
    return false, -1
}
 5
Author: Jim Hsiang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-04 04:38:12

Możesz użyć pakietu reflect do iteracji po interfejsie, którego konkretnym typem jest plasterek:

func HasElem(s interface{}, elem interface{}) bool {
    arrV := reflect.ValueOf(s)

    if arrV.Kind() == reflect.Slice {
        for i := 0; i < arrV.Len(); i++ {

            // XXX - panics if slice element points to an unexported struct field
            // see https://golang.org/pkg/reflect/#Value.Interface
            if arrV.Index(i).Interface() == elem {
                return true
            }
        }
    }

    return false
}

Https://play.golang.org/p/jL5UD7yCNq

 4
Author: Ethan Kennedy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-21 16:10:04

Jeśli nie jest możliwe użycie mapy do znajdowania przedmiotów na podstawie klucza, możesz rozważyć narzędzie goderive . Goderive generuje specyficzną dla danego typu implementację metody contains, dzięki czemu kod jest zarówno czytelny, jak i wydajny.

Przykład;

type Foo struct {
    Field1 string
    Field2 int
} 

func Test(m Foo) bool {
     var allItems []Foo
     return deriveContainsFoo(allItems, m)
}

Aby wygenerować metodę deriveContainsFoo:

  • zainstaluj goderive za pomocą go get -u github.com/awalterschulze/goderive
  • Uruchom goderive ./... w folderze workspace

Ta metoda zostanie wygenerowana dla deriveContains:

func deriveContainsFoo(list []Foo, item Foo) bool {
    for _, v := range list {
        if v == item {
            return true
        }
    }
    return false
}

Goderive ma wsparcie dla wielu innych przydatnych metod pomocniczych do stosowania funkcjonalnego stylu programowania w go.

 3
Author: Alexander van Trijffel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-08 09:43:34

Nie jestem pewien, czy leki generyczne są tu potrzebne. Potrzebujesz tylko umowy na pożądane zachowanie. Wykonanie następujących czynności nie jest niczym więcej niż to, co musiałbyś zrobić w innych językach, Jeśli chcesz, aby twoje własne obiekty zachowywały się w kolekcjach, na przykład przez nadpisanie Equals() i GetHashCode ().

type Identifiable interface{
    GetIdentity() string
}

func IsIdentical(this Identifiable, that Identifiable) bool{
    return (&this == &that) || (this.GetIdentity() == that.GetIdentity())
}

func contains(s []Identifiable, e Identifiable) bool {
    for _, a := range s {
        if IsIdentical(a,e) {
            return true
        }
    }
    return false
}
 2
Author: JonPen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-12 14:21:06

Obecnie w pakiecie Contains znajduje się funkcja slice. Możesz przeczytać dokumenty tutaj .

Przykładowe użycie:

if !slice.Contains(sliceVar, valueToFind) {
    //code here
}
 2
Author: Pajri Aprilio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-24 00:28:27

Stworzyłem bardzo prosty benchmark z rozwiązaniami z tych odpowiedzi.

Https://gist.github.com/NorbertFenk/7bed6760198800207e84f141c41d93c7

To nie jest prawdziwy benchmark, ponieważ początkowo nie wstawiłem zbyt wielu elementów, ale zapraszam do rozwidlenia i zmiany.

 1
Author: F. Norbert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-29 16:15:41

Myślę, że map [x]bool jest bardziej przydatny niż map[x] struct{}.

Indeksowanie mapy dla elementu, który nie jest obecny zwróci false, więc zamiast _, ok: = m [X], możesz po prostu powiedzieć m[X].

Ułatwia to zagnieżdżanie testów inkluzji w wyrażeniach.

 0
Author: Bill Burdick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-04 22:08:53

W innym wątku skomentowałem rozwiązanie tego problemu na dwa sposoby:

Pierwsza metoda:

func Find(slice interface{}, f func(value interface{}) bool) int {
    s := reflect.ValueOf(slice)
    if s.Kind() == reflect.Slice {
        for index := 0; index < s.Len(); index++ {
            if f(s.Index(index).Interface()) {
                return index
            }
        }
    }
    return -1
}

Użyj przykładu:

type UserInfo struct {
    UserId          int
}

func main() {
    var (
        destinationList []UserInfo
        userId      int = 123
    )
    
    destinationList = append(destinationList, UserInfo { 
        UserId          : 23,
    }) 
    destinationList = append(destinationList, UserInfo { 
        UserId          : 12,
    }) 
    
    idx := Find(destinationList, func(value interface{}) bool {
        return value.(UserInfo).UserId == userId
    })
    
    if idx < 0 {
        fmt.Println("not found")
    } else {
        fmt.Println(idx)    
    }
}

Druga metoda z mniejszym kosztem obliczeniowym:

func Search(length int, f func(index int) bool) int {
    for index := 0; index < length; index++ {
        if f(index) {
            return index
        }
    }
    return -1
}

Użyj przykładu:

type UserInfo struct {
    UserId          int
}

func main() {
    var (
        destinationList []UserInfo
        userId      int = 123
    )
    
    destinationList = append(destinationList, UserInfo { 
        UserId          : 23,
    }) 
    destinationList = append(destinationList, UserInfo { 
        UserId          : 123,
    }) 
    
    idx := Search(len(destinationList), func(index int) bool {
        return destinationList[index].UserId == userId
    })
    
    if  idx < 0 {
        fmt.Println("not found")
    } else {
        fmt.Println(idx)    
    }
}
 0
Author: omotto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-07 08:52:34

Styl go:

func Contains(n int, match func(i int) bool) bool {
    for i := 0; i < n; i++ {
        if match(i) {
            return true
        }
    }
    return false
}


s := []string{"a", "b", "c", "o"}
// test if s contains "o"
ok := Contains(len(s), func(i int) bool {
    return s[i] == "o"
})
 -1
Author: Roy O'Young,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-15 12:09:36

Może to być uważane za nieco "hakerskie", ale w zależności od rozmiaru i zawartości plasterka, możesz połączyć plasterek ze sobą i przeszukać ciąg znaków.

Na przykład masz kawałek zawierający pojedyncze wartości słowa (np. "tak", "nie", "może"). Wyniki te są dołączane do kawałka. Jeśli chcesz sprawdzić, czy ten kawałek zawiera jakieś "może" Wyniki, możesz użyć

exSlice := ["yes", "no", "yes", "maybe"]
if strings.Contains(strings.Join(exSlice, ","), "maybe") {
  fmt.Println("We have a maybe!")
}

To, jak jest to odpowiednie, zależy od wielkości plastra i długości jego członków. Może wystąpić występ lub kwestie przydatności dla dużych plastrów lub długich wartości, ale dla mniejszych plastrów o skończonej wielkości i prostych wartościach jest ważne jednoliniowe, aby osiągnąć pożądany rezultat.

 -1
Author: chopper24,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-07 05:14:31