Проверьте, содержит ли срез строки определенное значение в Go

Каков наилучший способ проверить, находится ли определенное значение в строчном фрагменте? Я бы использовал Set на других языках, но Go не имеет его.

Моя лучшая попытка - это пока:

package main

import "fmt"

func main() {
    list := []string{"a", "b", "x"}
    fmt.Println(isValueInList("b", list))
    fmt.Println(isValueInList("z", list))
}

func isValueInList(value string, list []string) bool {
    for _, v := range list {
        if v == value {
            return true
        }
    }
    return false
}

http://play.golang.org/p/gkwMz5j09n

Это решение должно быть хорошо для небольших фрагментов, но что делать для срезов со многими элементами?

Ответы

Ответ 1

Если у вас есть фрагмент строк в произвольном порядке, поиск значения в срезе требует O (n) времени. Это относится ко всем языкам.

Если вы собираетесь выполнять поиск снова и снова, вы можете использовать другие структуры данных для ускорения поиска. Однако для построения этих структур требуется не менее O (n) времени. Таким образом, вы получите преимущества только в том случае, если вы выполняете поиск с использованием структуры данных более одного раза.

Например, вы можете загрузить свои строки в карту. Тогда для поиска потребуется время O (1). Вставки также принимают время O (1), заставляя начальную сборку взять время O (n):

set := make(map[string]bool)
for _, v := range list {
    set[v] = true
}

fmt.Println(set["b"])

Вы также можете отсортировать фрагмент строки, а затем выполнить двоичный поиск. Бинарные запросы происходят в O (log (n)) времени. Здание может принимать время O (n * log (n)).

sort.Strings(list)
i := sort.SearchStrings(list, "b")
fmt.Println(i < len(list) && list[i] == "b")

Хотя теоретически с учетом бесконечного числа значений, карта быстрее, на практике очень вероятно, что поиск отсортированного списка будет быстрее. Вам нужно сравнить его самостоятельно.

Ответ 2

Для замены наборов вы можете использовать map[string]whatever. Это не будет легче, чем вы можете себе представить (там указатель на значение, которое вам не нужно), но, кроме написания собственной хеш-таблицы, он наиболее эффективен и довольно оптимизирован по мере его создания.

set := make(map[string]uint8)

Чтобы поставить элемент:

set[item]=1

Чтобы проверить, присутствует ли элемент:

_, ok = set[item]

Это обычная идиома в Go. Если ok истинно, тогда элемент присутствовал. Если ok имеет значение false, элемент отсутствует.

Ответ 3

Вы можете использовать карту и иметь значение, например. bool

m := map[string] bool {"a":true, "b":true, "x":true}
if m["a"] { // will be false if "a" is not in the map
    //it was in the map
}

Также есть sort, чтобы вы могли сортировать и бинарно искать свои фрагменты