Golang: Множественные операции над слайсами
Go не имеет встроенного типа множества, но с помощью стандартного пакета slices и сторонней библиотеки lo можно легко реализовать основные операции, такие как проверка вхождения, удаление дубликатов, объединение и пересечение.
Библиотека lo — это популярный набор утилит для работы со срезами и другими структурами данных в Go. Она дополняет возможности стандартной библиотеки, предоставляя функции высокого уровня, которых нет в slices. Мы используем её для упрощения написания кода и повышения читаемости, особенно для таких операций, как объединение или пересечение срезов.
Проверка вхождения элемента
Для проверки наличия элемента в срезе используем slices.Contains():
import (
"fmt"
"slices"
)
func main() {
nums := []int{1, 2, 3}
fmt.Println(slices.Contains(nums, 2)) // => true
fmt.Println(slices.Contains(nums, 5)) // => false
}Удаление дубликатов
Удалить дубликаты можно с помощью slices.Compact(), но только для отсортированных данных. Если порядок элементов важен, используем lo.Uniq():
import "github.com/samber/lo"
nums := []int{2, 1, 2, 3, 1}
unique := lo.Uniq(nums)
fmt.Println(unique) // => [2 1 3]Объединение (union)
Стандартный пакет slices не предоставляет функции объединения, поэтому используем lo.Union():
a := []int{1, 2, 3}
b := []int{3, 4, 5}
all := lo.Union(a, b)
fmt.Println(all) // => [1 2 3 4 5]Пересечение (intersection)
Для пересечения тоже используем lo.Intersect:
a := []int{1, 2, 3}
b := []int{2, 3, 4}
common := lo.Intersect(a, b)
fmt.Println(common) // => [2 3]Разность (difference)
Разность множеств можно вычислить через lo.Difference():
a := []int{1, 2, 3}
b := []int{2, 4}
onlyA, _ := lo.Difference(a, b)
fmt.Println(onlyA) // => [1 3]Симметрическая разность
Симметрическая разность — это элементы, которые есть в одном из срезов, но не в обоих.
Её можно получить через lo.Difference(), комбинируя оба результата:
a := []int{1, 2, 3}
b := []int{2, 4}
onlyA, onlyB := lo.Difference(a, b)
symDiff := append(onlyA, onlyB...)
fmt.Println(symDiff) // => [1 3 4]Вывод
Используя пакет slices для базовых операций и lo для более продвинутых функций (объединение, пересечение, разность), можно работать со срезами в Go так же удобно, как с множествами в других языках.
Задание
Реализуйте функцию CompareProductLists(oldList, newList []string) (added, removed []string), которая сравнивает два списка товаров и возвращает два среза:
added— товары, появившиеся вnewList, которых не было вoldList.removed— товары, которые были вoldList, но отсутствуют вnewList.
Порядок элементов в результатах не имеет значения.
Примеры:
oldList := []string{"apple", "banana", "orange"}
newList := []string{"banana", "kiwi", "apple"}
added, removed := CompareProductLists(oldList, newList)
// added = ["kiwi"], removed = ["orange"]
added, removed = CompareProductLists([]string{}, []string{"milk"})
// added = ["milk"], removed = []
added, removed = CompareProductLists([]string{"bread"}, []string{})
// added = [], removed = ["bread"]Полезное
Golang: Множественные операции над слайсами
Go не имеет встроенного типа множества, но с помощью стандартного пакета slices и сторонней библиотеки lo можно легко реализовать основные операции, такие как проверка вхождения, удаление дубликатов, объединение и пересечение.
Библиотека lo — это популярный набор утилит для работы со срезами и другими структурами данных в Go. Она дополняет возможности стандартной библиотеки, предоставляя функции высокого уровня, которых нет в slices. Мы используем её для упрощения написания кода и повышения читаемости, особенно для таких операций, как объединение или пересечение срезов.
Проверка вхождения элемента
Для проверки наличия элемента в срезе используем slices.Contains():
import (
"fmt"
"slices"
)
func main() {
nums := []int{1, 2, 3}
fmt.Println(slices.Contains(nums, 2)) // => true
fmt.Println(slices.Contains(nums, 5)) // => false
}Удаление дубликатов
Удалить дубликаты можно с помощью slices.Compact(), но только для отсортированных данных. Если порядок элементов важен, используем lo.Uniq():
import "github.com/samber/lo"
nums := []int{2, 1, 2, 3, 1}
unique := lo.Uniq(nums)
fmt.Println(unique) // => [2 1 3]Объединение (union)
Стандартный пакет slices не предоставляет функции объединения, поэтому используем lo.Union():
a := []int{1, 2, 3}
b := []int{3, 4, 5}
all := lo.Union(a, b)
fmt.Println(all) // => [1 2 3 4 5]Пересечение (intersection)
Для пересечения тоже используем lo.Intersect:
a := []int{1, 2, 3}
b := []int{2, 3, 4}
common := lo.Intersect(a, b)
fmt.Println(common) // => [2 3]Разность (difference)
Разность множеств можно вычислить через lo.Difference():
a := []int{1, 2, 3}
b := []int{2, 4}
onlyA, _ := lo.Difference(a, b)
fmt.Println(onlyA) // => [1 3]Симметрическая разность
Симметрическая разность — это элементы, которые есть в одном из срезов, но не в обоих.
Её можно получить через lo.Difference(), комбинируя оба результата:
a := []int{1, 2, 3}
b := []int{2, 4}
onlyA, onlyB := lo.Difference(a, b)
symDiff := append(onlyA, onlyB...)
fmt.Println(symDiff) // => [1 3 4]Вывод
Используя пакет slices для базовых операций и lo для более продвинутых функций (объединение, пересечение, разность), можно работать со срезами в Go так же удобно, как с множествами в других языках.
Задание
Реализуйте функцию CompareProductLists(oldList, newList []string) (added, removed []string), которая сравнивает два списка товаров и возвращает два среза:
added— товары, появившиеся вnewList, которых не было вoldList.removed— товары, которые были вoldList, но отсутствуют вnewList.
Порядок элементов в результатах не имеет значения.
Примеры:
oldList := []string{"apple", "banana", "orange"}
newList := []string{"banana", "kiwi", "apple"}
added, removed := CompareProductLists(oldList, newList)
// added = ["kiwi"], removed = ["orange"]
added, removed = CompareProductLists([]string{}, []string{"milk"})
// added = ["milk"], removed = []
added, removed = CompareProductLists([]string{"bread"}, []string{})
// added = [], removed = ["bread"]Полезное
Ваше упражнение проверяется по этим тестам
// Тесты
package solution
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestCompareProductLists(t *testing.T) {
tests := []struct {
name string
oldList []string
newList []string
expectedAdded []string
expectedRem []string
}{
{
name: "One added and one removed",
oldList: []string{"apple", "banana", "orange"},
newList: []string{"banana", "kiwi", "apple"},
expectedAdded: []string{"kiwi"},
expectedRem: []string{"orange"},
},
{
name: "All new",
oldList: []string{},
newList: []string{"milk"},
expectedAdded: []string{"milk"},
expectedRem: []string{},
},
{
name: "All removed",
oldList: []string{"bread"},
newList: []string{},
expectedAdded: []string{},
expectedRem: []string{"bread"},
},
{
name: "No changes",
oldList: []string{"water"},
newList: []string{"water"},
expectedAdded: []string{},
expectedRem: []string{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
added, removed := CompareProductLists(tt.oldList, tt.newList)
assert.ElementsMatch(t, tt.expectedAdded, added)
assert.ElementsMatch(t, tt.expectedRem, removed)
})
}
}Решение учителя откроется через:
20:00
