Skip to content

Instantly share code, notes, and snippets.

@scottcagno
Created September 19, 2023 20:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scottcagno/835bcc93d6ad990086c620eefd69d4a4 to your computer and use it in GitHub Desktop.
Save scottcagno/835bcc93d6ad990086c620eefd69d4a4 to your computer and use it in GitHub Desktop.
Simple beginnings of a search engine type thing...
package main
import (
"fmt"
"io"
"log"
"os"
"regexp"
"sort"
"strconv"
"strings"
)
func main() {
data := [][]string{
{"foo", "bar", "baz"},
{"one", "two", "three", "four"},
{"five", "one", "two", "nine"},
{"three", "eleven", "eighteen"},
}
items := OpenSortedItems(data)
res := Search("eleven", items)
fmt.Println(res, data[3][1])
}
type Item interface {
Search(pattern string) *Result
}
type Result struct {
Ident string
Offsets []int
}
func Search(pattern string, items []Item) *Result {
c := make(chan *Result)
search := func(i int) {
c <- items[i].Search(pattern)
}
for i := range items {
go search(i)
}
for {
select {
case res := <-c:
if res == nil {
continue
}
fmt.Printf("Got result: %+v\n", res)
return res
}
}
//return <-c
}
func fanIn[T any](input1, input2 <-chan T) <-chan T {
c := make(chan T)
go func() {
for {
select {
case v := <-input1:
c <- v
case v := <-input2:
c <- v
}
}
}()
return c
}
// FileItem is an example implementation of an Item
// that wraps a file...
type FileItem struct {
fp *os.File
}
func OpenFileItems(files ...string) []Item {
fileItems := make([]Item, 0)
for _, file := range files {
fp, err := os.Open(file)
if err != nil {
log.Println("Error opening file...")
}
fileItems = append(fileItems, &FileItem{fp: fp})
}
return fileItems
}
func (fi *FileItem) Search(pattern string) *Result {
reg, err := regexp.CompilePOSIX(pattern)
if err != nil {
return nil
}
b, err := io.ReadAll(fi.fp)
if err != nil {
return nil
}
idx := reg.FindIndex(b)
if idx == nil {
return nil
}
return &Result{
Ident: fi.fp.Name(),
Offsets: idx,
}
}
// SortedItem is an example implementation of an Item
// that wraps a sorted set of things...
type SortedItem struct {
name string
data []string
}
func OpenSortedItems(datasets [][]string) []Item {
sortedItems := make([]Item, 0)
for i, str := range datasets {
sortedItems = append(sortedItems, &SortedItem{
name: strconv.Itoa(i),
data: str,
})
}
return sortedItems
}
func (si *SortedItem) Len() int {
return len(si.data)
}
func (si *SortedItem) Less(i, j int) bool {
return si.data[i] < si.data[j]
}
func (si *SortedItem) Swap(i, j int) {
si.data[i], si.data[j] = si.data[j], si.data[i]
}
func (si *SortedItem) Search(pattern string) *Result {
if !sort.IsSorted(si) {
sort.Stable(si)
}
i, found := sort.Find(si.Len(), func(i int) int {
return strings.Compare(pattern, si.data[i])
})
if !found {
return nil
}
return &Result{
Ident: si.name,
Offsets: []int{i},
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment