1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-12-13 05:50:27 +00:00

Separate pathographic sorting code

This commit is contained in:
Mikhail Chekan 2021-09-01 01:12:55 +08:00 committed by Timur Ismagilov
parent 9f48ded254
commit 0b2e52b99b
2 changed files with 38 additions and 25 deletions

View File

@ -3,6 +3,7 @@ package hyphae
import ( import (
"strings" "strings"
"sort"
) )
// YieldExistingHyphae iterates over all hyphae and yields all existing ones. // YieldExistingHyphae iterates over all hyphae and yields all existing ones.
@ -33,6 +34,40 @@ func FilterTextHyphae(src chan *Hypha) chan *Hypha {
return sink return sink
} }
// PathographicSort sorts paths inside the source channel, preserving the path tree structure
func PathographicSort(src chan string) <-chan string {
out := make(chan string)
go func() {
// To make it unicode-friendly and lean, we cast every string into rune slices, sort, and only then cast them back
raw := make([][]rune, 0)
for h := range src {
raw = append(raw, []rune(h))
}
sort.Slice(raw, func(i, j int) bool {
const slash rune = 47 // == '/'
// Classic lexicographical sort with a twist
c := 0
for {
if c == len(raw[i]) { return true }
if c == len(raw[j]) { return false }
if raw[i][c] == raw[j][c] {
c++
} else {
// The twist: subhyphae-awareness is about pushing slash upwards
if raw[i][c] == slash { return true }
if raw[j][c] == slash { return false }
return raw[i][c] < raw[j][c]
}
}
})
for _, name := range raw {
out <- string(name)
}
close(out)
}()
return out
}
// Subhyphae returns slice of subhyphae. // Subhyphae returns slice of subhyphae.
func (h *Hypha) Subhyphae() []*Hypha { func (h *Hypha) Subhyphae() []*Hypha {
hyphae := []*Hypha{} hyphae := []*Hypha{}

View File

@ -1,7 +1,6 @@
package shroom package shroom
import ( import (
"sort"
"strings" "strings"
"github.com/bouncepaw/mycorrhiza/hyphae" "github.com/bouncepaw/mycorrhiza/hyphae"
@ -11,37 +10,16 @@ import (
func YieldHyphaNamesContainingString(query string) <-chan string { func YieldHyphaNamesContainingString(query string) <-chan string {
query = util.CanonicalName(query) query = util.CanonicalName(query)
out := make(chan string) out := make(chan string)
sorted := hyphae.PathographicSort(out)
go func() { go func() {
// To make it unicode-friendly and lean, we cast every string into rune slices, sort, and only then cast them back
raw := make([][]rune, 0)
for h := range hyphae.YieldExistingHyphae() { for h := range hyphae.YieldExistingHyphae() {
if hyphaNameMatchesString(h.Name, query) { if hyphaNameMatchesString(h.Name, query) {
raw = append(raw, []rune(h.Name)) out <- h.Name
} }
} }
sort.Slice(raw, func(i, j int) bool {
const slash rune = 47 // == '/'
// Classic lexicographical sort with a twist
c := 0
for {
if c == len(raw[i]) { return true }
if c == len(raw[j]) { return false }
if raw[i][c] == raw[j][c] {
c++
} else {
// The twist: subhyphae-awareness is about pushing slash upwards
if raw[i][c] == slash { return true }
if raw[j][c] == slash { return false }
return raw[i][c] < raw[j][c]
}
}
})
for _, name := range raw {
out <- string(name)
}
close(out) close(out)
}() }()
return out return sorted
} }
// This thing gotta be changed one day, when a hero has time to implement a good searching algorithm. // This thing gotta be changed one day, when a hero has time to implement a good searching algorithm.