Skip to content

Instantly share code, notes, and snippets.

@tcolgate
Created February 26, 2020 17:11
Show Gist options
  • Save tcolgate/107e1c59e9f43cd6be843e64831fa5c3 to your computer and use it in GitHub Desktop.
Save tcolgate/107e1c59e9f43cd6be843e64831fa5c3 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"log"
"math/rand"
"sort"
"time"
)
type intslice struct {
vals []int
i int
curr int
}
func newslice() *intslice {
size := 2 + rand.Intn(10)
sl := make([]int, size)
for i := range sl {
sl[i] = 1 + rand.Intn(10_000_000)
}
sort.Ints(sl)
return &intslice{
vals: sl,
}
}
func (intslice) Err() error {
return nil
}
func (intslice) Close() error {
return nil
}
func (sl *intslice) Value() int {
return sl.curr
}
func (sl *intslice) Next() bool {
if sl.i >= len(sl.vals) {
return false
}
sl.curr = sl.vals[sl.i]
sl.i++
return true
}
type iterator interface {
Next() bool
Value() int
Err() error
Close() error
}
type mergeSortIterator struct {
is []iterator
curVals []int
next int
lastUsed int
}
func mergeSort(is []iterator) *mergeSortIterator {
return &mergeSortIterator{
is: is,
lastUsed: -1,
}
}
func (ms *mergeSortIterator) Next() bool {
for i := range ms.is {
log.Printf("is[%d]: %v", i, ms.is[i])
}
if len(ms.is) == 0 {
return false
}
if ms.curVals == nil {
ms.curVals = make([]int, len(ms.is))
}
smallest := -1
smallestn := -1
n := 0
for i, it := range ms.is {
if !it.Next() {
it.Close()
continue
}
ms.is[n] = it
if ms.lastUsed == -1 || i == ms.lastUsed {
ms.curVals[n] = it.Value()
}
if smallest == -1 || ms.curVals[n] < smallest {
smallest = ms.curVals[n]
smallestn = n
}
n++
}
log.Printf("smallest: %d n: %d", smallest, smallestn)
if n == 0 {
return false
}
ms.is = ms.is[:n]
ms.curVals = ms.curVals[:n]
ms.next = smallest
ms.lastUsed = smallestn
return true
}
func (ms *mergeSortIterator) Value() int {
return ms.next
}
func (ms *mergeSortIterator) Err() error {
return nil
}
func (ms *mergeSortIterator) Close() error {
return nil
}
func main() {
rand.Seed(time.Now().UnixNano())
sls := make([]iterator, rand.Intn(10))
for i := range sls {
sls[i] = newslice()
}
mit := mergeSort(sls)
for mit.Next() {
fmt.Printf("v: %v\n", mit.Value())
}
if err := mit.Err(); err != nil {
log.Printf("err: %v", err)
}
}
@tcolgate
Copy link
Author

I need to merge a series of streams of data. The streams are naturally orderered (it's actually log data)., but must finally be presented to the user in order. This is an initial "correct" implementation. The final approach needs to be non-blocking when iterating over to backfill values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment