github.com/isyscore/isc-gobase@v1.5.3-0.20231218061332-cbc7451899e9/isc/stream.go (about) 1 package isc 2 3 import ( 4 "sort" 5 ) 6 7 // A Stream is a stream that can be used to do stream processing. 8 type Stream[T any] struct { 9 source <-chan T 10 } 11 12 // StreamJust converts the given arbitrary items to a Stream. 13 func StreamJust[T any](items ...T) Stream[T] { 14 source := make(chan T, len(items)) 15 for _, e := range items { 16 source <- e 17 } 18 close(source) 19 return StreamRange(source) 20 } 21 22 // AllMatch returns whether all elements of this stream match the provided predicate. 23 // May not evaluate the predicate on all elements if not necessary for determining the result. 24 // If the stream is empty then true is returned and the predicate is not evaluated. 25 func (s Stream[T]) AllMatch(predicate func(T) bool) bool { 26 for item := range s.source { 27 if !predicate(item) { 28 // make sure the former goroutine not block, and current func returns fast. 29 go StreamDrain(s.source) 30 return false 31 } 32 } 33 return true 34 } 35 36 // AnyMatch returns whether any elements of this stream match the provided predicate. 37 // May not evaluate the predicate on all elements if not necessary for determining the result. 38 // If the stream is empty then false is returned and the predicate is not evaluated. 39 func (s Stream[T]) AnyMatch(predicate func(T) bool) bool { 40 for item := range s.source { 41 if predicate(item) { 42 // make sure the former goroutine not block, and current func returns fast. 43 go StreamDrain(s.source) 44 return true 45 } 46 } 47 return false 48 } 49 50 // NoneMatch returns whether all elements of this stream don't match the provided predicate. 51 // May not evaluate the predicate on all elements if not necessary for determining the result. 52 // If the stream is empty then true is returned and the predicate is not evaluated. 53 func (s Stream[T]) NoneMatch(predicate func(T) bool) bool { 54 for item := range s.source { 55 if predicate(item) { 56 go StreamDrain(s.source) 57 return false 58 } 59 } 60 return true 61 } 62 63 func (s Stream[T]) Map(fn func(T) T) Stream[T] { 64 source := make(chan T) 65 for item := range s.source { 66 source <- fn(item) 67 } 68 return StreamRange(source) 69 } 70 71 // Sort sorts the items from the underlying source. 72 func (s Stream[T]) Sort(less func(T, T) bool) Stream[T] { 73 var items []T 74 for item := range s.source { 75 items = append(items, item) 76 } 77 sort.Slice(items, func(i, j int) bool { 78 return less(items[i], items[j]) 79 }) 80 return StreamJust(items...) 81 } 82 83 // Distinct removes the duplicated items base on the given keySelector. 84 func (s Stream[T]) Distinct(keySelector func(T) T) Stream[T] { 85 source := make(chan T) 86 m := make(map[any]T) 87 for item := range s.source { 88 m[keySelector(item)] = item 89 } 90 for _, v := range m { 91 source <- v 92 } 93 return StreamRange(source) 94 } 95 96 // ForEach seals the Stream with the fn on each item, no successive operations. 97 func (s Stream[T]) ForEach(fn func(T)) { 98 for item := range s.source { 99 fn(item) 100 } 101 } 102 103 //FirsVal returns the first element,channel is FIFO,so first goroutine will get head element or nil 104 func (s Stream[T]) FirsVal() any { 105 for item := range s.source { 106 go StreamDrain(s.source) 107 return item 108 } 109 return nil 110 } 111 112 //First returns the first element,channel is FIFO,so first goroutine will get head element 113 func (s Stream[T]) First(valueSelector func(T) bool) Stream[T] { 114 source := make(chan T) 115 go func() { 116 for item := range s.source { 117 if valueSelector(item) { 118 source <- item 119 break 120 } 121 } 122 }() 123 close(source) 124 return StreamRange(source) 125 } 126 127 // LastVal returns the last item, or nil if no items. 128 func (s Stream[T]) LastVal() (item T) { 129 for item = range s.source { 130 } 131 return 132 } 133 134 // Last returns the last item, or nil if no items. 135 func (s Stream[T]) Last(valueSelector func(any) bool) Stream[T] { 136 source := make(chan T) 137 var lastValue T 138 for item := range s.source { 139 if valueSelector(item) { 140 lastValue = item 141 } 142 } 143 source <- lastValue 144 close(source) 145 return StreamRange(source) 146 } 147 148 //Filter Returns a list containing only elements matching the given predicate. 149 func (s Stream[T]) Filter(predicate func(T) bool) Stream[T] { 150 source := make(chan T) 151 for item := range s.source { 152 if predicate(item) { 153 source <- item 154 } 155 } 156 defer close(source) 157 return StreamRange(source) 158 } 159 160 func StreamRange[T any](source <-chan T) Stream[T] { 161 return Stream[T]{ 162 source: source, 163 } 164 } 165 166 // StreamDrain drains the given channel. 167 func StreamDrain[T any](ch <-chan T) { 168 for range ch { 169 } 170 } 171 172 // Done waits all upstreaming operations to be done. 173 func (s Stream[T]) Done() { 174 StreamDrain(s.source) 175 }