Как найти элементы, которые есть в одном срезе, но отсутствуют в другом (разность множеств)?

Ответ

Эту задачу, известную как "нахождение разности множеств", в Go эффективнее всего решать с помощью map для создания хеш-сета.

Алгоритм:

  1. Создать map[T]struct{} (где T — тип элементов среза) для хранения элементов второго среза. Использование пустой структуры struct{} в качестве значения является идиоматичным, так как она не занимает памяти.
  2. Пройтись по второму срезу (sliceB) и добавить все его элементы в map в качестве ключей.
  3. Пройтись по первому срезу (sliceA) и для каждого элемента проверить, есть ли он в map. Если элемента в map нет, добавить его в результирующий срез.

Этот подход имеет сложность O(N+M), где N и M — длины срезов, что гораздо эффективнее вложенных циклов со сложностью O(N*M).

package main

import "fmt"

// difference возвращает элементы, которые есть в a, но нет в b.
func difference(a, b []int) []int {
    // Создаем сет для быстрой проверки наличия элементов из b
    setB := make(map[int]struct{}, len(b))
    for _, item := range b {
        setB[item] = struct{}{}
    }

    var result []int
    // Проверяем каждый элемент из a
    for _, item := range a {
        if _, found := setB[item]; !found {
            result = append(result, item)
        }
    }
    return result
}

func main() {
    sliceA := []int{1, 2, 3, 4, 5, 6}
    sliceB := []int{2, 4, 7}

    // Находим элементы, которые есть в sliceA, но нет в sliceB
    diff := difference(sliceA, sliceB)
    fmt.Println(diff) // Вывод: [1 3 5 6]
}