github.com/koko1123/flow-go-1@v0.29.6/model/flow/identifierList.go (about) 1 package flow 2 3 import ( 4 "bytes" 5 "math/rand" 6 "sort" 7 8 "github.com/rs/zerolog/log" 9 ) 10 11 // IdentifierList defines a sortable list of identifiers 12 type IdentifierList []Identifier 13 14 // Len returns length of the IdentiferList in the number of stored identifiers. 15 // It satisfies the sort.Interface making the IdentifierList sortable. 16 func (il IdentifierList) Len() int { 17 return len(il) 18 } 19 20 // Lookup converts the Identifiers to a lookup table. 21 func (il IdentifierList) Lookup() map[Identifier]struct{} { 22 lookup := make(map[Identifier]struct{}, len(il)) 23 for _, id := range il { 24 lookup[id] = struct{}{} 25 } 26 return lookup 27 } 28 29 // Less returns true if element i in the IdentifierList is less than j based on its identifier. 30 // Otherwise it returns true. 31 // It satisfies the sort.Interface making the IdentifierList sortable. 32 func (il IdentifierList) Less(i, j int) bool { 33 // bytes package already implements Comparable for []byte. 34 switch bytes.Compare(il[i][:], il[j][:]) { 35 case -1: 36 return true 37 case 0, 1: 38 return false 39 default: 40 log.Error().Msg("not fail-able with `bytes.Comparable` bounded [-1, 1].") 41 return false 42 } 43 } 44 45 // Swap swaps the element i and j in the IdentifierList. 46 // It satisfies the sort.Interface making the IdentifierList sortable. 47 func (il IdentifierList) Swap(i, j int) { 48 il[j], il[i] = il[i], il[j] 49 } 50 51 func (il IdentifierList) Strings() []string { 52 var list []string 53 for _, id := range il { 54 list = append(list, id.String()) 55 } 56 57 return list 58 } 59 60 func (il IdentifierList) Copy() IdentifierList { 61 cpy := make(IdentifierList, 0, il.Len()) 62 return append(cpy, il...) 63 } 64 65 // Contains returns whether this identifier list contains the target identifier. 66 func (il IdentifierList) Contains(target Identifier) bool { 67 for _, id := range il { 68 if target == id { 69 return true 70 } 71 } 72 return false 73 } 74 75 // Union returns a new identifier list containing the union of `il` and `other`. 76 // There are no duplicates in the output. 77 func (il IdentifierList) Union(other IdentifierList) IdentifierList { 78 // stores the output, the union of the two lists 79 union := make(IdentifierList, 0, len(il)+len(other)) 80 // efficient lookup to avoid duplicates 81 lookup := make(map[Identifier]struct{}) 82 83 // add all identifiers, omitted duplicates 84 for _, identifier := range append(il.Copy(), other...) { 85 if _, exists := lookup[identifier]; exists { 86 continue 87 } 88 union = append(union, identifier) 89 lookup[identifier] = struct{}{} 90 } 91 92 return union 93 } 94 95 // DeterministicSample returns deterministic random sample from the `IdentifierList` using the given seed 96 func (il IdentifierList) DeterministicSample(size uint, seed int64) IdentifierList { 97 rand.Seed(seed) 98 return il.Sample(size) 99 } 100 101 // Sample returns random sample of length 'size' of the ids 102 // [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher–Yates_shuffle). 103 func (il IdentifierList) Sample(size uint) IdentifierList { 104 return Sample(size, il...) 105 } 106 107 // Filter will apply a filter to the identifier list. 108 func (il IdentifierList) Filter(filter IdentifierFilter) IdentifierList { 109 var dup IdentifierList 110 IDLoop: 111 for _, identifier := range il { 112 if !filter(identifier) { 113 continue IDLoop 114 } 115 dup = append(dup, identifier) 116 } 117 return dup 118 } 119 120 func (il IdentifierList) Sort(less IdentifierOrder) IdentifierList { 121 dup := il.Copy() 122 sort.Slice(dup, func(i int, j int) bool { 123 return less(dup[i], dup[j]) 124 }) 125 return dup 126 } 127 128 // Sorted returns whether the list is sorted by the input ordering. 129 func (il IdentifierList) Sorted(less IdentifierOrder) bool { 130 for i := 0; i < len(il)-1; i++ { 131 a := il[i] 132 b := il[i+1] 133 if !less(a, b) { 134 return false 135 } 136 } 137 return true 138 }