Ответ
В Go нет встроенной функции для проверки наличия элемента в слайсе, которая была бы доступна во всех версиях языка, но существует несколько стандартных подходов. Выбор зависит от версии Go, размера слайса и частоты операций поиска.
1. Простой перебор (цикл for)
Это самый базовый и универсальный способ, который работает во всех версиях Go.
Преимущества:
- Простота и наглядность.
- Не требует дополнительных зависимостей или версий Go.
Недостатки:
- Низкая производительность на больших слайсах.
Сложность: O(n), где n — количество элементов в слайсе.
func containsString(slice []string, item string) bool {
for _, v := range slice {
if v == item {
return true
}
}
return false
}
2. Generic-функция (Go 1.18+)
С появлением дженериков в Go 1.18 можно написать универсальную функцию для любых сравниваемых типов (comparable).
Преимущества:
- Переиспользуемый код для разных типов (
int,string,float64и т.д.). - Сохраняет типобезопасность.
Сложность: O(n).
func Contains[T comparable](slice []T, item T) bool {
for _, v := range slice {
if v == item {
return true
}
}
return false
}
3. Пакет slices (Go 1.21+)
Начиная с версии Go 1.21, в стандартной библиотеке появился пакет slices, который содержит функцию Contains. Это предпочтительный способ для современных проектов.
Преимущества:
- Идиоматичный и стандартный способ.
- Код становится чище и короче.
Сложность: O(n).
import "slices"
func check() {
mySlice := []string{"a", "b", "c"}
// Вернет true
found := slices.Contains(mySlice, "b")
}
4. Использование map для частых проверок
Если проверки на наличие элемента выполняются многократно на одном и том же наборе данных, эффективнее будет преобразовать слайс в map.
Преимущества:
- Очень высокая скорость поиска после первоначального построения
map.
Недостатки:
- Требует дополнительной памяти для хранения
map. - Затраты на первоначальное преобразование слайса в
map(сложность O(n)).
Сложность:
- Построение
map: O(n) - Поиск в
map: O(1) (в среднем)
Этот подход оправдан, когда количество операций поиска значительно превышает размер слайса.
// Преобразуем слайс в set (map[T]struct{}) для быстрого поиска
stringSlice := []string{"apple", "banana", "orange"}
set := make(map[string]struct{}, len(stringSlice))
for _, v := range stringSlice {
set[v] = struct{}{}
}
// Проверка выполняется мгновенно
if _, ok := set["banana"]; ok {
// Элемент найден
}
Использование struct{} в качестве значения map является идиомой в Go для создания множества (set), так как пустая структура не занимает памяти.
Ответ 18+ 🔞
Слушай, а вот это реально пиздец, как в Го нет нормальной встроенной хуйни для проверки, есть ли элемент в слайсе. Ну, то есть, она есть, но только с определённых версий, а так — приходится выёбываться. Но варианты есть, выбирай по обстановке, блядь.
1. Тупой перебор (цикл for)
Это как ломом лед рубить — просто, понятно и работает везде, даже на древнем Го.
Что хорошего:
- Не надо думать, написал и пошёл.
- Никаких новых версий не требует.
Что плохого:
- Если слайс размером с овердохуища, то всё, пиздец, будет тормозить как старая кобыла.
Скорость: O(n), где n — это сколько там у тебя элементов накопилось.
func containsString(slice []string, item string) bool {
for _, v := range slice {
if v == item {
return true
}
}
return false
}
2. Дженерики (Go 1.18+)
Тут уже поинтереснее, с версии 1.18 можно написать одну функцию на все случаи жизни, для любых типов, которые можно сравнивать.
Что хорошего:
- Одна функция и для строк, и для чисел, и для всего, что
comparable. Удобно, ёпта. - Типы не теряются, всё типобезопасно.
Скорость: Всё те же O(n), волшебства нет.
func Contains[T comparable](slice []T, item T) bool {
for _, v := range slice {
if v == item {
return true
}
}
return false
}
3. Пакет slices (Go 1.21+)
А вот это уже красота, блядь! С версии 1.21 в стандартной библиотеке завезли пакет slices, и там есть готовая Contains. Вот это сейчас самый правильный путь, если пишешь на свежем Го.
Что хорошего:
- Красиво, идиоматично, одна строчка.
- Не надо свою велосипедную хуйню городить.
Скорость: Да всё та же O(n), но зато стильно.
import "slices"
func check() {
mySlice := []string{"a", "b", "c"}
// Вернёт true, ёбана
found := slices.Contains(mySlice, "b")
}
4. Использование map для частых проверок
А вот это, сука, для настоящих перфекционистов! Если тебе надо один слайс тыкать раз сто проверкой, то лучше его один раз преобразовать в map и потом наслаждаться жизнью.
Что хорошего:
- Скорость поиска — просто пиздец какая, почти мгновенно.
Что плохого:
- Жрёт память, как не в себя, под
mapнадо место. - Сначала надо этот
mapпостроить, а это тоже время.
Скорость:
- Построить
map: O(n) (один раз потерпеть) - Найти в
map: O(1) (а вот это уже охуенно!)
Смысл есть, только если ищешь часто, а данные не меняются каждую секунду.
// Делаем из слайса сет (map[T]struct{}) для быстрого поиска
stringSlice := []string{"apple", "banana", "orange"}
set := make(map[string]struct{}, len(stringSlice))
for _, v := range stringSlice {
set[v] = struct{}{}
}
// Проверка — раз плюнуть
if _, ok := set["banana"]; ok {
// Ну вот, нашёл, доволен как слон
}
Кстати, struct{} в качестве значения — это такая местная приколюха, чтоб память не жрало. Гениально и просто, в рот меня чих-пых!