github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/cmd/juju/commands/statusnaturalsort.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package commands 5 6 import ( 7 "fmt" 8 "strconv" 9 "strings" 10 "unicode" 11 ) 12 13 type naturally []string 14 15 func (n naturally) Len() int { 16 return len(n) 17 } 18 19 func (n naturally) Swap(a, b int) { 20 n[a], n[b] = n[b], n[a] 21 } 22 23 // Less sorts by non-numeric prefix and numeric suffix 24 // when one exists. 25 func (n naturally) Less(a, b int) bool { 26 aPrefix, aNumber := splitAtNumber(n[a]) 27 bPrefix, bNumber := splitAtNumber(n[b]) 28 if aPrefix == bPrefix { 29 return aNumber < bNumber 30 } 31 return n[a] < n[b] 32 } 33 34 // splitAtNumber splits given string into prefix and numeric suffix. 35 // If no numeric suffix exists, full original string is returned as 36 // prefix with -1 as a suffix. 37 func splitAtNumber(str string) (string, int) { 38 i := strings.LastIndexFunc(str, func(r rune) bool { 39 return !unicode.IsDigit(r) 40 }) + 1 41 if i == len(str) { 42 // no numeric suffix 43 return str, -1 44 } 45 n, err := strconv.Atoi(str[i:]) 46 if err != nil { 47 panic(fmt.Sprintf("parsing number %v: %v", str[i:], err)) // should never happen 48 } 49 return str[:i], n 50 }