package util import ( "reflect" "strconv" "strings" ) // StrInList determines if a string in a slice of strings func StrInSlice(needle string, haystack []string) bool { for _, straw := range haystack { if straw == needle { return true } } return false } // StrInSliceIdx returns the indexes of string matches in a slice of strings func StrInSliceIdx(m string, l []string) (il []int) { for i, s := range l { if s == m { il = append(il, i) } } return } // IntInSliceIdx returns the indexes of integer matches in a slice of integers func IntInSliceIdx(m int, l []int) (il []int) { for i, s := range l { if s == m { il = append(il, i) } } return } // IntInList determines if an int is in a list func IntInSlice(m int, l []int) bool { for _, s := range l { if s == m { return true } } return false } // UniqueInts removes duplicates from a slice of integers and returns the cleaned slice of integers func UniqueInts(ol []int) (nl []int) { for _, i := range ol { f := false for _, ni := range nl { if ni == i { f = true break } } if !f { nl = append(nl, i) } } return } // UniqueStrings removes duplicates from a slice of strings and returns the cleaned slice of strings func UniqueStrings(ol []string) (nl []string) { for _, i := range ol { f := false for _, ni := range nl { if ni == i { f = true break } } if !f { nl = append(nl, i) } } return } // ItoaList takes a list of integers and returns a list of strings func ItoaList(s []int) (r []string) { for _, k := range s { r = append(r, strconv.Itoa(k)) } return } // AtoiList takes a list of strings and returns a list of integers. If any strings are not able to be converted, it simply skips over them func AtoiList(s []string) (r []int) { for _, k := range s { if i, err := strconv.Atoi(k); err == nil { r = append(r, i) } } return } //Slicer splits a list of items int a set of chunks where b is the number in each list //source: https://groups.google.com/forum/#!topic/golang-nuts/yyS_mr5C-oE func Slicer(a interface{}, b int) [][]interface{} { val := reflect.ValueOf(a) origLen := val.Len() outerLen := origLen / b if origLen%b > 0 { outerLen++ } // Make the output slices with all the correct lengths c := make([][]interface{}, outerLen) for i := range c { newLen := b if origLen-(i*b+newLen) < 0 { newLen = origLen % b } c[i] = make([]interface{}, newLen) for j := range c[i] { c[i][j] = val.Index(i*b + j).Interface() } } return c } // CreateBatches splits a slice of integers in to batches (slices) of integers of the given size func CreateIntBatches(sourceSlice []int, batchSize int) (dl [][]int) { l := len(sourceSlice) c := 0 var i []int for x := 0; x <= (l / batchSize); x++ { if c+batchSize > l { i = sourceSlice[c:] if len(i) != 0 { dl = append(dl, sourceSlice[c:]) } } else { i = sourceSlice[c : c+batchSize] if len(i) != 0 { dl = append(dl, sourceSlice[c:c+batchSize]) } } c += batchSize } return } // CreateStringBatches splits a slice of strings in to batches (slices) of strings of the given size func CreateStringBatches(items []string, split int) (dl [][]string) { l := len(items) c := 0 var i []string for x := 0; x <= (l / split); x++ { if c+split > l { i = items[c:] if len(i) != 0 { dl = append(dl, items[c:]) } } else { i = items[c : c+split] if len(i) != 0 { dl = append(dl, items[c:c+split]) } } c += split } return } // Atoi returns converts a string to an integer and returns the int. If conversion fails it returns -99999 func Atoi(str string) int { if n, err := strconv.Atoi(str); err == nil { return n } return -9999 } // AtoiPointer returns a pointer if it is able to convert the string to int, or nil if it encounters an error func AtoiPointer(str string) *int { if n, err := strconv.Atoi(str); err == nil { return &n } return nil } // ListIndexToi attempts to convert the item at idx to a int or -9999 if idx is out of bounds or not a number func ListIndexToi(items []string, idx int) int { if idx < len(items) { return Atoi(items[idx]) } return -9999 } // Diff finds any missing or extra lines between two '\n' seperated strings. func Diff(os, ns string) (string, bool) { ol := strings.Split(strings.TrimRight(os, " "), "\n") nl := strings.Split(strings.TrimRight(ns, " "), "\n") var diff []string var change bool for _, o := range ol { if StrInSlice(o, nl) { diff = append(diff, o) continue } diff = append(diff, "- "+o) change = true } for _, n := range nl { if n == "" { continue } if !StrInSlice(n, ol) { diff = append(diff, "+ "+n) change = true } } return strings.Join(diff, "\n"), change } // StringSliceCompare compares two slices of strings to see if they are the same func StringSliceCompare(a, b []string) bool { if a == nil && b == nil { return true } if a == nil || b == nil { return false } if len(a) != len(b) { return false } for i := range a { if a[i] != b[i] { return false } } return true } // StringSliceToString combines the members of a slice of strings in to a single string func StringSliceToString(slice []string) string { var output string for i := range slice { if i > 0 { output = output + " " } output = output + slice[i] } return output } // AnyStrInSlice looks to see if any members of the needles stack is in the haystack func AnyStrInSlice(needles []string, haystack []string) bool { for _, needle := range needles { for _, straw := range haystack { if straw == needle { return true } } } return false } // SlicesContainSameStrings takes two slices of strings and checks if everything in the first slice is in the second, and vice versa func SlicesContainSameStrings(a, b []string) bool { // Some short circuits if len(a) != len(b) { return false } if len(a) == 0 && len(b) == 0 { return true } // Make sure everything in a is in b for _, aVal := range a { found := false for _, bVal := range b { if aVal == bVal { found = true // Found a match, move to next aVal continue } } // If we didn't find a match in 'b' for a value in 'a', short circuit and return false if !found { return false } } // Make sure everything in b is in a for _, bVal := range b { found := false for _, aVal := range a { if bVal == aVal { found = true // Found a match, move to next bVal continue } } // If we didn't find a match in 'a' for a value in 'b', short circuit and return false if !found { return false } } // Every value in a has a match in b, and vice versa. return true } // SlicesContainSameInts takes two slices of integers and checks if everything in the first slice is in the second, and vice versa func SlicesContainSameInts(a, b []int) bool { // Some short circuits if len(a) != len(b) { return false } if len(a) == 0 && len(b) == 0 { return true } // Make sure everything in a is in b for _, aVal := range a { found := false for _, bVal := range b { if aVal == bVal { found = true // Found a match, move to next aVal continue } } // If we didn't find a match in 'b' for a value in 'a', short circuit and return false if !found { return false } } // Make sure everything in b is in a for _, bVal := range b { found := false for _, aVal := range a { if bVal == aVal { found = true // Found a match, move to next bVal continue } } // If we didn't find a match in 'a' for a value in 'b', short circuit and return false if !found { return false } } // Every value in a has a match in b, and vice versa. return true }