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
