Skip to content

Instantly share code, notes, and snippets.

@earwin
Created September 11, 2024 00:33
Show Gist options
  • Save earwin/149740749c8aaccde5ea626169c32735 to your computer and use it in GitHub Desktop.
Save earwin/149740749c8aaccde5ea626169c32735 to your computer and use it in GitHub Desktop.
An implementation of column.IterableOrderedMap for clickhouse-go
package clickhousex
import (
"cmp"
"github.com/ClickHouse/clickhouse-go/v2/lib/column"
"iter"
"slices"
)
type OrderedMap[K any, V any] struct {
entries []entry[K, V]
}
type entry[K any, V any] struct {
key K
value V
}
type iterator[K any, V any] struct {
m *OrderedMap[K, V]
i int
}
func ToOrderedMap[M ~map[K]V, K cmp.Ordered, V any](m M) *OrderedMap[K, V] {
om := &OrderedMap[K, V]{entries: make([]entry[K, V], 0, len(m))}
for k, v := range m {
om.Put(k, v)
}
slices.SortFunc(om.entries, func(i, j entry[K, V]) int { return cmp.Compare(i.key, j.key) })
return om
}
func SeqToOrderedMap[K cmp.Ordered, V any](seq iter.Seq2[K, V]) *OrderedMap[K, V] {
om := &OrderedMap[K, V]{entries: make([]entry[K, V], 0)}
for k, v := range seq {
om.Put(k, v)
}
slices.SortFunc(om.entries, func(i, j entry[K, V]) int { return cmp.Compare(i.key, j.key) })
return om
}
func (m *OrderedMap[K, V]) Put(key any, value any) {
m.entries = append(m.entries, entry[K, V]{key.(K), value.(V)})
}
func (m *OrderedMap[K, V]) Entries() iter.Seq2[K, V] {
return func(yield func(k K, v V) bool) {
for _, e := range m.entries {
if !yield(e.key, e.value) {
return
}
}
}
}
func (m *OrderedMap[K, V]) Keys() iter.Seq[K] {
return func(yield func(k K) bool) {
for _, e := range m.entries {
if !yield(e.key) {
return
}
}
}
}
func (m *OrderedMap[K, V]) Values() iter.Seq[V] {
return func(yield func(v V) bool) {
for _, e := range m.entries {
if !yield(e.value) {
return
}
}
}
}
func (m *OrderedMap[K, V]) Iterator() column.MapIterator { return &iterator[K, V]{m: m, i: -1} }
func (i *iterator[K, V]) Next() bool { i.i++; return i.i < len(i.m.entries) }
func (i *iterator[K, V]) Key() any { return i.m.entries[i.i].key }
func (i *iterator[K, V]) Value() any { return i.m.entries[i.i].value }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment