Skip to content

Instantly share code, notes, and snippets.

@mewmew
Forked from philippbayer/natural_sort.go
Created June 30, 2019 18:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mewmew/923da5e1f0bbfc770a9573a979fce32a to your computer and use it in GitHub Desktop.
Save mewmew/923da5e1f0bbfc770a9573a979fce32a to your computer and use it in GitHub Desktop.
A perverted kind of natural sort in golang
package main
import (
"fmt"
"log"
"sort"
"strconv"
"strings"
"unicode"
)
// Mostly based on http://golang.org/pkg/sort/#example__sortKeys
// Since name is a string, don't need to implement fancy structs
type By func(name1, name2 string) bool
func (by By) Sort(names []string) {
ps := &nameSorter{
names: names,
by: by,
}
sort.Sort(ps)
}
type nameSorter struct {
names []string
by func(name1, name2 string) bool
}
func getNumber(name string) (new_s int) {
// Need a key to sort the names by. In this case, it's the number contained in the name
// Example: M23abcdeg ---> 23
// Of course, this tends to break hideously once complicated stuff is involved:
// For example, 'ülda123dmwak142.e2dööööwq,' what do you sort by here?
// Could be 123, could be 142, or 2, could be 1231422 (this takes the last case)
s := make([]string, 0)
for _, element := range name {
if unicode.IsNumber(element) {
s = append(s, string(element))
}
}
new_s, err := strconv.Atoi(strings.Join(s, ""))
if err != nil {
log.Fatal(err) // Just die
}
return new_s
}
// Need some inbuilt methods
func (s *nameSorter) Swap(i, j int) {
s.names[i], s.names[j] = s.names[j], s.names[i]
}
func (s *nameSorter) Len() int {
return len(s.names)
}
func (s *nameSorter) Less(i, j int) bool {
return s.by(s.names[i], s.names[j])
}
func main() {
// closure to sort by
name_number := func(name1, name2 string) bool {
return getNumber(name1) < getNumber(name2)
}
fmt.Println("Before:")
example_slice := []string{"9999", "123bla", "1bla", "dawjdwa50awdnwdkj"}
fmt.Println(example_slice)
By(name_number).Sort(example_slice)
fmt.Println("After:")
fmt.Println(example_slice)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment