{wcademy}

Как убрать повторяющиеся элементы из слайса?

January 10, 2021

Как уникализировать слайс в Go

Давайте напишем функцию 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]
}
🚀  Если узнал из статьи что-то полезное, ставь лайк и подписывайся на наш канал в Телеграм или группу ВК. Обсудить статью можно в нашем уютном чатике 😏

© 2019 - 2022, {wcademy}