Skip to content

Instantly share code, notes, and snippets.

@letschers
Created April 13, 2024 17:32
Show Gist options
  • Select an option

  • Save letschers/50ff71b9b1716d17d07616d292d707f9 to your computer and use it in GitHub Desktop.

Select an option

Save letschers/50ff71b9b1716d17d07616d292d707f9 to your computer and use it in GitHub Desktop.

Revisions

  1. letschers created this gist Apr 13, 2024.
    119 changes: 119 additions & 0 deletions generics.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,119 @@
    package main

    import (
    "fmt"
    "reflect"
    "slices"
    "strings"
    )

    type Obj[K any, V comparable] struct {
    key K
    value V
    }

    func compareValues[T comparable](a, b T) int {
    var (
    valueA = reflect.ValueOf(a)
    valueB = reflect.ValueOf(b)
    )

    if valueA.Type() != valueB.Type() {
    panic("types are not comparable")
    }

    switch valueA.Kind() {
    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    if valueA.Int() < valueB.Int() {
    return -1
    } else if valueA.Int() > valueB.Int() {
    return 1
    } else {
    return 0
    }
    case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
    if valueA.Uint() < valueB.Uint() {
    return -1
    } else if valueA.Uint() > valueB.Uint() {
    return 1
    } else {
    return 0
    }
    case reflect.Float32, reflect.Float64:
    if valueA.Float() < valueB.Float() {
    return -1
    } else if valueA.Float() > valueB.Float() {
    return 1
    } else {
    return 0
    }
    case reflect.String:
    return strings.Compare(valueA.String(), valueB.String())
    default:
    panic("unsupported type")
    }
    }

    func sortFunc[K, V comparable](obj1, obj2 Obj[K, V]) int {
    return compareValues(obj1.value, obj2.value)
    }

    type ObjArr[K comparable, V comparable] []Obj[K, V]

    func (a ObjArr[K, V]) Sort() {
    slices.SortFunc(a, sortFunc)
    }

    func mapToSlice[K, V comparable](m map[K]V) ObjArr[K, V] {
    var slice []Obj[K, V]

    for k, v := range m {
    slice = append(slice, Obj[K, V]{
    key: k,
    value: v,
    })
    }

    return slice
    }

    func sliceToMap[K, V comparable](s ObjArr[K, V]) map[K]V {
    var m = make(map[K]V)

    for _, v := range s {
    m[v.key] = v.value
    }

    return m
    }

    func main() {
    var m = map[string]int{
    "second": 2,
    "forth": 4,
    "first": 1,
    "third": 3,
    "fifth": 5,
    }

    var s = mapToSlice(m)

    fmt.Println(s) // [{second 2} {forth 4} {first 1} {third 3} {fifth 5}]
    s.Sort()
    fmt.Println(s) // [{first 1} {second 2} {third 3} {forth 4} {fifth 5}]

    var m2 = map[string]string{
    "second": "b",
    "forth": "d",
    "first": "a",
    "third": "c",
    "fifth": "e",
    }

    var s2 = mapToSlice(m2)

    fmt.Println(s2) // [{second b} {forth d} {first a} {third c} {fifth e}]
    s2.Sort()
    fmt.Println(s2) // [{first a} {second b} {third c} {forth d} {fifth e}]

    }