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  }