bitbucket.org/ai69/amoy@v0.2.3/sequence.go (about)

     1  package amoy
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"strings"
     7  )
     8  
     9  // ParseIntSequence parses sequences like "9-12,10,20" into slices of int like [9, 10, 11, 12, 20].
    10  func ParseIntSequence(s, splitSep, rangeSep string) ([]int, error) {
    11  	if splitSep == rangeSep || len(splitSep) == 0 || len(rangeSep) == 0 {
    12  		return nil, fmt.Errorf("invalid separators")
    13  	}
    14  	var (
    15  		temp       []int
    16  		numA, numB int
    17  		err        error
    18  	)
    19  	parts := strings.Split(s, splitSep)
    20  	for _, p := range parts {
    21  		ns := strings.Split(p, rangeSep)
    22  		if len(ns) == 1 {
    23  			if numA, err = Atoi(ns[0]); err != nil {
    24  				return nil, err
    25  			}
    26  			temp = append(temp, numA)
    27  		} else if len(ns) == 2 {
    28  			if numA, err = Atoi(ns[0]); err != nil {
    29  				return nil, err
    30  			}
    31  			if numB, err = Atoi(ns[1]); err != nil {
    32  				return nil, err
    33  			}
    34  			if numA > numB {
    35  				return nil, fmt.Errorf("invalid range bound: %d > %d", numA, numB)
    36  			}
    37  			for i := numA; i <= numB; i++ {
    38  				temp = append(temp, i)
    39  			}
    40  		} else {
    41  			return nil, fmt.Errorf("invalid range format: %s", p)
    42  		}
    43  	}
    44  	result := DistinctInts(temp)
    45  	sort.Ints(result)
    46  	return result, nil
    47  }
    48  
    49  // MergeIntSequence merges int slices like [8, 8, 9, 10, 20, 12]. into sequences like "8-10,12,20".
    50  func MergeIntSequence(num []int, splitSep, rangeSep string) string {
    51  	if len(num) == 0 {
    52  		return ""
    53  	}
    54  	sort.Ints(num)
    55  	var (
    56  		result    []string
    57  		beginNum  int
    58  		lastNum   int
    59  		saveRange = func(bg, lt int) {
    60  			if bg == lt {
    61  				result = append(result, fmt.Sprintf("%d", bg))
    62  			} else {
    63  				result = append(result, fmt.Sprintf("%d%s%d", bg, rangeSep, lt))
    64  			}
    65  		}
    66  	)
    67  	for i, n := range num {
    68  		if i == 0 {
    69  			beginNum = n
    70  		} else if n != lastNum+1 && n != lastNum {
    71  			saveRange(beginNum, lastNum)
    72  			beginNum = n
    73  		}
    74  		lastNum = n
    75  	}
    76  	saveRange(beginNum, lastNum)
    77  	return strings.Join(result, splitSep)
    78  }
    79  
    80  // DistinctInts returns a new slice with the same order but without duplicate int elements.
    81  func DistinctInts(ori []int) []int {
    82  	exist := make(map[int]struct{})
    83  	for _, n := range ori {
    84  		exist[n] = struct{}{}
    85  	}
    86  	result := make([]int, 0)
    87  	for _, n := range ori {
    88  		if _, ok := exist[n]; ok {
    89  			result = append(result, n)
    90  			delete(exist, n)
    91  		}
    92  	}
    93  	return result
    94  }