Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subset check with slices in Go

I am looking for a efficient way to check if a slice is a subset of another. I could simply iterate over them to check, but I feel there has to be a better way.

E.g.

{1, 2, 3} is a subset of {1, 2, 3, 4}
{1, 2, 2} is NOT a subset of {1, 2, 3, 4}

What is the best way to do this efficiently?

Thanks!

like image 880
Matt Olan Avatar asked Sep 18 '13 17:09

Matt Olan


People also ask

How can I check if two slices are equal Golang?

To check if two slices are equal, write a custom function that compares their lengths and corresponding elements in a loop. You can also use the reflect. DeepEqual() function that compares two values recursively, which means it traverses and checks the equality of the corresponding data values at each level.

Are slices passed by reference in Go?

Go slice is reference typeA slice is a reference type in Go. This means that when we assign a reference to a new variable or pass a slice to a function, the reference to the slice is copied. In the code example, we define a slice and assign the slice to a new variable.

How do I find a slice in Golang?

In the Go slice, you can search an element of string type in the given slice of strings with the help of SearchStrings() function. This function searches for the given element in a sorted slice of strings and returns the index of that element if present in the given slice.


1 Answers

I think the most common way to solve a subset problem is via a map.

package main

import "fmt"

// subset returns true if the first array is completely
// contained in the second array. There must be at least
// the same number of duplicate values in second as there
// are in first.
func subset(first, second []int) bool {
    set := make(map[int]int)
    for _, value := range second {
        set[value] += 1
    }

    for _, value := range first {
        if count, found := set[value]; !found {
            return false
        } else if count < 1 {
            return false
        } else {
            set[value] = count - 1
        }
    }

    return true
}

func main() {
    fmt.Println(subset([]int{1, 2, 3}, []int{1, 2, 3, 4}))
    fmt.Println(subset([]int{1, 2, 2}, []int{1, 2, 3, 4}))
}

The ability to check duplicate values is relatively uncommon. The code above solves the problem as asked (see: http://play.golang.org/p/4_7Oh-fgDQ) though. If you plan on having duplicate values, you'll have to keep a count like the code above does. If there will not be duplicate values, you can solve the problem more compactly by using a boolean for the map value instead of an integer.

like image 157
icub3d Avatar answered Oct 13 '22 12:10

icub3d