Created
August 22, 2013 00:29
-
-
Save johnwesonga/6301924 to your computer and use it in GitHub Desktop.
Go code that ensures elements in a slice are unique
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "fmt" | |
func uniqueNonEmptyElementsOf(s []string) []string { | |
unique := make(map[string]bool, len(s)) | |
us := make([]string, len(unique)) | |
for _, elem := range s { | |
if len(elem) != 0 { | |
if !unique[elem] { | |
us = append(us, elem) | |
unique[elem] = true | |
} | |
} | |
} | |
return us | |
} | |
func main() { | |
names := []string{"John", "Peter", "Jim", "John", "Ken", "Pete", "Jimmy"} | |
fmt.Println(uniqueNonEmptyElementsOf(names)) | |
} |
Agreed! All other examples were merely integer based, not strings
func UniqueSliceElements[T comparable](inputSlice []T) []T {
uniqueSlice := make([]T, 0, len(inputSlice))
seen := make(map[T]bool, len(inputSlice))
for _, element := range inputSlice {
if !seen[element] {
uniqueSlice = append(uniqueSlice, element)
seen[element] = true
}
}
return uniqueSlice
}
func UniqueSliceElements[T comparable](inputSlice []T) []T {
uniqueSlice := make([]T, 0, len(inputSlice))
seen := make(map[T]struct{}, len(inputSlice))
for _, element := range inputSlice {
if !seen[element] {
uniqueSlice = append(uniqueSlice, element)
seen[element] = struct{}{}
}
}
return uniqueSlice
}
@Demznak 👍 for smaller memory footprint :)
the seen test probably should be if _, ok := seen[element]; !ok {
Just as an experiment...
package main
import (
"fmt"
"math/rand"
"testing"
)
var inputSlice []int
func UniqueSliceElementsStruct[T comparable](inputSlice []T) []T {
uniqueSlice := make([]T, 0, len(inputSlice))
seen := make(map[T]struct{}, len(inputSlice))
for _, element := range inputSlice {
if _, ok := seen[element]; !ok {
uniqueSlice = append(uniqueSlice, element)
seen[element] = struct{}{}
}
}
return uniqueSlice
}
func UniqueSliceElementsBool[T comparable](inputSlice []T) []T {
uniqueSlice := make([]T, 0, len(inputSlice))
seen := make(map[T]bool, len(inputSlice))
for _, element := range inputSlice {
if !seen[element] {
uniqueSlice = append(uniqueSlice, element)
seen[element] = true
}
}
return uniqueSlice
}
func BenchmarkUniqueSliceElementsStruct(b *testing.B) {
b.N = 10000
for i := 0; i < b.N; i++ {
UniqueSliceElementsStruct(inputSlice)
}
}
func BenchmarkUniqueSliceElementsBool(b *testing.B) {
b.N = 10000
for i := 0; i < b.N; i++ {
UniqueSliceElementsBool(inputSlice)
}
}
type BenchResult struct {
name string
result testing.BenchmarkResult
}
func main() {
// Generate a slice
inputSlice = make([]int, 100000)
// Fill the slice with random integers between 0 and 999
for i := range inputSlice {
inputSlice[i] = rand.Intn(1000)
}
results := []BenchResult{
{
name: "BenchmarkUniqueSliceElementsStruct",
result: testing.Benchmark(BenchmarkUniqueSliceElementsStruct),
},
{
name: "BenchmarkUniqueSliceElementsBool",
result: testing.Benchmark(BenchmarkUniqueSliceElementsBool),
},
}
fmt.Printf("%-*s | ", 35, "Bench")
fmt.Printf("%-*s | ", 9, "Mem alloc")
fmt.Printf("%-*s | ", 12, "Bytes alloc")
fmt.Printf("%-*s | ", 9, "Runs")
fmt.Printf("%-*s", 9, "Time")
fmt.Println()
for i := 0; i < len(results); i++ {
fmt.Printf("%-*s | ", 35, results[i].name)
fmt.Printf("%-*d | ", 9, results[i].result.MemAllocs)
fmt.Printf("%-*d | ", 12, results[i].result.Bytes)
fmt.Printf("%-*d | ", 9, results[i].result.N)
fmt.Printf("%-*s", 9, results[i].result.T)
fmt.Println()
}
}
go run main.go
Bench | Mem alloc | Bytes alloc | Runs | Time
BenchmarkUniqueSliceElementsStruct | 30618 | 0 | 10000 | 7.3797462s
BenchmarkUniqueSliceElementsBool | 30612 | 0 | 10000 | 7.1591373s
@cr1cr1 The experiment was interesting Ж)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks! Need this. You create a map for fast look up and take only unique elements.