Simulating Sets in Go Using Maps

Introduction

Welcome to our Simulating Sets in Go lesson! In Go, there's no built-in type specifically called a "set." However, the concept of a set — a collection that stores unique elements — can be emulated using other data structures provided by the language, such as maps. Sets are incredibly useful when you need to ensure that elements in a collection are unique. In this lesson, you'll explore how to create and manage set-like collections in Go by implementing a Set custom struct.

Creating and Manipulating Sets

In Go, we can simulate a set by leveraging maps. A map's keys naturally represent unique elements due to their uniqueness within the context of the map. Below, we'll demonstrate how to create and manipulate a set-like structure using a custom Set struct.

package main

import "fmt"

// Set is a custom struct to simulate a set using a map.
type Set struct {
    elements map[int]struct{}
}

// NewSet initializes and returns a new set.
func NewSet() *Set {
    return &Set{elements: make(map[int]struct{})}
}

func main() {
    mySet := NewSet()
    elements := []int{1, 2, 3, 4, 5, 5, 5}

    for _, elem := range elements {
        mySet.Add(elem) // Add element to the set, ensuring uniqueness.
    }

    // Print each unique element in the set.
    for key := range mySet.elements {
        fmt.Println(key) // Output: 1 2 3 4 5
    }
}

In this example, the Set struct encapsulates the map, ensuring element uniqueness. The choice of using struct{} as the map's value type is intentional—it occupies no memory (0 bytes), unlike other types such as bool. This design decision leverages memory efficiency.

Inserting and Deleting Elements

To simulate basic set operations, we define receiver functions (methods) for the Set struct:

  • Inserting an Element: The Add() method updates the map with the key being the element and value as an empty struct, ensuring the element's existence in the set.
  • Deleting an Element: The Remove() method removes the element by deleting its key from the map.
  • Checking for Membership: The Has() method checks for the presence of a key in the map, hence confirming an element's membership in the set.
func (s *Set) Add(v int) {
    s.elements[v] = struct{}{}
}

func (s *Set) Has(v int) bool {
    _, exists := s.elements[v]
    return exists
}

func (s *Set) Remove(v int) {
    delete(s.elements, v)
}

func main() {
    mySet := NewSet()
    mySet.Add(1)
    mySet.Add(2)
    mySet.Add(3)

    if mySet.Has(1) {
        fmt.Println("Element 1 exists")
    }

    mySet.Remove(1)

    if !mySet.Has(1) {
        fmt.Println("Element 1 no longer exists")
    }
}
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal