1package interactors 2 3import ( 4 "regexp" 5 "sort" 6 "strings" 7) 8 9type simpleSet map[string]bool 10 11var unicode = regexp.MustCompile("[^\x00-\x7F]+") 12 13func (s simpleSet) Contains(other string) bool { 14 enabled, exists := s[other] 15 return exists && enabled 16} 17 18// Returns the different of two slices of strings; effectively a set arithmetic operation on two slices of strings 19func DistinctValues(slice1, slice2 []string) []string { 20 sets := []simpleSet{ 21 sliceToSimpleSet(slice1), 22 sliceToSimpleSet(slice2), 23 } 24 25 discardKeysFromOther(sets[0], sets[1]) 26 discardKeysFromOther(sets[1], sets[0]) 27 28 var exclusiveValues []string 29 for _, k := range allKeys(sets...) { 30 for _, set := range sets { 31 if set[k] == true { 32 exclusiveValues = append(exclusiveValues, k) 33 } 34 } 35 } 36 sort.Strings(exclusiveValues) 37 return exclusiveValues 38} 39 40func SetSubtract(add, negate []string) []string { 41 toRemove := sliceToSimpleSet(negate) 42 var result []string 43 for _, a := range add { 44 if !toRemove.Contains(a) { 45 result = append(result, a) 46 } 47 } 48 return result 49} 50 51func SetUnion(slice1, slice2 []string) []string { 52 union := allKeys( 53 sliceToSimpleSet( 54 append( 55 slice1, 56 slice2..., 57 ), 58 ), 59 ) 60 sort.Strings(union) 61 return union 62} 63 64func sliceToSimpleSet(s []string) simpleSet { 65 m := make(simpleSet, len(s)) 66 for _, val := range s { 67 m[val] = true 68 } 69 return m 70} 71 72func discardKeysFromOther(s1, s2 simpleSet) { 73 for k := range s1 { 74 if _, exists := s2[k]; exists { 75 s2[k] = false 76 } 77 } 78} 79 80func allKeys(sets ...simpleSet) []string { 81 totalCount := 0 82 for _, s := range sets { 83 totalCount += len(s) 84 } 85 86 keys := make([]string, totalCount) 87 index := 0 88 for _, s := range sets { 89 for k := range s { 90 keys[index] = k 91 index++ 92 } 93 } 94 return keys 95} 96 97func FilterNoUnicode(s string) string { 98 badCharacters := sliceToSimpleSet( 99 unicode.FindAllString(s, -1), 100 ) 101 if len(badCharacters) == 0 { 102 return s 103 } 104 validCharacters := make([]string, 0, len(s)) 105 for _, rune_ := range s { 106 char := string(rune_) 107 if !badCharacters.Contains(char) { 108 validCharacters = append(validCharacters, char) 109 } 110 } 111 return strings.Join( 112 validCharacters, 113 "", 114 ) 115} 116