Как убрать повторяющиеся элементы из слайса?
January 10, 2021
Давайте напишем функцию Dedupe
, которая оставляет в слайсе или массиве только уникальные элементы. В смысле уникализирует (дедуплицирует, называйте как хотите) его элементы.
- В го пока нет дженериков, поэтому нам придётся продублировать функцию для каждого из необходимых нам типов.
- Можно было бы написать универсальную функцию на основе пустого интерфейса и рефлексии, но так делать не надо.
- Используем
make
для создания словаря и нового среза для уникальных значений сразу нужного нам размера. - Значение словаря — пустая структура, это нужно для экономии памяти.
- Срез
uniq
нам нужен только для сохранения порядка, если порядок не важен — можно переписать на использование только словаря (можете считать — вам дз). - Итерируемся по элементам cлайса и словаря, чтобы проверить, не были ли они добавлены ранее.
- Используем функцию
append
для добавления уникальных значений в слайс уникальных элементов.
func DedupeInts(arr []int) []int {
m, uniq := make(map[int]struct{}), make([]int, 0, len(arr))
for _, v := range arr {
if _, ok := m[v]; !ok {
m[v], uniq = struct{}{}, append(uniq, v)
}
}
return uniq
}
func DedupeFloat64s(arr []float64) []float64 {
m, uniq := make(map[float64]struct{}), make([]float64, 0, len(arr))
for _, v := range arr {
if _, ok := m[v]; !ok {
m[v], uniq = struct{}{}, append(uniq, v)
}
}
return uniq
}
func DedupeStrings(arr []string) []string {
m, uniq := make(map[string]struct{}), make([]string, 0, len(arr))
for _, v := range arr {
if _, ok := m[v]; !ok {
m[v], uniq = struct{}{}, append(uniq, v)
}
}
return uniq
}
Пример использования:
func main() {
fmt.Println(DedupeStrings([]string{"a", "b", "a", "c"})) // [a b c]
}
В качестве бонуса, универсальная функция на будущем go2 для любого типа:
package main
import (
"fmt"
)
func Dedupe[T comparable](arr []T) []T {
m, uniq := make(map[T]struct{}), make([]T, 0, len(arr))
for _, v := range arr {
if _, ok := m[v]; !ok {
m[v], uniq = struct{}{}, append(uniq, v)
}
}
return uniq
}
func main() {
fmt.Println(Dedupe([]string{"a", "b", "a", "c"})) // [a b c]
}
🚀 Если узнал из статьи что-то полезное, ставь лайк и подписывайся на наш канал в Телеграм или группу ВК. Обсудить статью можно в нашем уютном чатике 😏