Created
July 8, 2016 20:39
-
-
Save jrop/5f9d3aa75161bcbd61865ef6e2f5d558 to your computer and use it in GitHub Desktop.
Slowdash (Golang)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"reflect" | |
"sort" | |
) | |
// Item is a generic item | |
// type Item interface{} | |
// Collection is a generic collection | |
type Collection struct { | |
Data interface{} | |
} | |
// OrderableCollection is an ordered collection | |
type OrderableCollection struct { | |
Collection Collection | |
Comparator func(a, b reflect.Value) bool | |
} | |
// Len is for sorting | |
func (oc OrderableCollection) Len() int { | |
return reflect.ValueOf(oc.Collection.Data).Len() | |
} | |
// Less is for sorting | |
func (oc OrderableCollection) Less(i, j int) bool { | |
cValue := reflect.ValueOf(oc.Collection.Data) | |
return oc.Comparator(cValue.Index(i), cValue.Index(j)) | |
} | |
// Swap is for sorting | |
func (oc OrderableCollection) Swap(i, j int) { | |
data := reflect.ValueOf(oc.Collection.Data) | |
x, y := data.Index(i).Interface(), data.Index(j).Interface() | |
data.Index(j).Set(reflect.ValueOf(x)) | |
data.Index(i).Set(reflect.ValueOf(y)) | |
} | |
// NewCollection creates a new collection | |
func NewCollection(data interface{}) Collection { | |
return Collection{Data: data} | |
} | |
// Map maps a collection | |
func (a Collection) Map(f func(item interface{}) interface{}) Collection { | |
aValue := reflect.ValueOf(a.Data) | |
aLen := aValue.Len() | |
newData := make([]interface{}, aLen) | |
for i := 0; i < aLen; i++ { | |
newData[i] = f(aValue.Index(i).Interface()) | |
} | |
return Collection{Data: newData} | |
} | |
// Filter filters a collection | |
func (a Collection) Filter(f func(item interface{}) bool) Collection { | |
aValue := reflect.ValueOf(a.Data) | |
aLen := aValue.Len() | |
newData := reflect.MakeSlice(reflect.TypeOf(a.Data), 0, aLen) | |
for i := 0; i < aLen; i++ { | |
if f(aValue.Index(i).Interface()) { | |
newData = reflect.Append(newData, aValue.Index(i)) | |
} | |
} | |
return Collection{Data: newData.Interface()} | |
} | |
// GroupBy groups a collection | |
func (a Collection) GroupBy(f func(item interface{}) interface{}) map[interface{}][]interface{} { | |
aValue := reflect.ValueOf(a.Data) | |
aLen := aValue.Len() | |
result := make(map[interface{}][]interface{}) | |
for i := 0; i < aLen; i++ { | |
groupKey := f(aValue.Index(i).Interface()) | |
if result[groupKey] == nil { | |
result[groupKey] = make([]interface{}, 0) | |
} | |
result[groupKey] = append(result[groupKey], aValue.Index(i).Interface()) | |
} | |
return result | |
} | |
// SortBy sort a collection | |
func (a Collection) SortBy(f func(item interface{}) interface{}) Collection { | |
aCopy := a.Map(func(item interface{}) interface{} { | |
return item | |
}) | |
comparator := func(a, b reflect.Value) bool { | |
_a := reflect.ValueOf(f(a.Interface())) | |
_b := reflect.ValueOf(f(b.Interface())) | |
if _a.Type() != _b.Type() { | |
panic("Unuequal types") | |
} | |
switch _a.Interface().(type) { | |
case string: | |
return _a.Interface().(string) < _b.Interface().(string) | |
case int: | |
return _a.Interface().(int) < _b.Interface().(int) | |
default: | |
panic("Unsupported type for comparison") | |
} | |
} | |
oc := OrderableCollection{Collection: aCopy, Comparator: comparator} | |
sort.Sort(oc) | |
return aCopy | |
} | |
// Find finds a value | |
func (a Collection) Find(f func(item interface{}) bool) (interface{}, bool) { | |
var val interface{} | |
found := false | |
aValue := reflect.ValueOf(a.Data) | |
aLen := aValue.Len() | |
for i := 0; i < aLen; i++ { | |
if f(aValue.Index(i).Interface()) { | |
val = aValue.Index(i).Interface() | |
found = true | |
return val, found | |
} | |
} | |
return val, found | |
} | |
// MustFind finds a value | |
func (a Collection) MustFind(f func(item interface{}) bool) interface{} { | |
val, ok := a.Find(f) | |
if !ok { | |
panic("Item not found") | |
} | |
return val | |
} | |
// Contains returns true if the collection contains an item that matches the predicate | |
func (a Collection) Contains(f func(item interface{}) bool) bool { | |
_, ok := a.Find(f) | |
return ok | |
} | |
// UniqueBy trims out duplicates | |
func (a Collection) UniqueBy(f func(item interface{}) interface{}) Collection { | |
aValue := reflect.ValueOf(a.Data) | |
aLen := aValue.Len() | |
newData := reflect.MakeSlice(aValue.Type(), 0, 0) | |
for i := 0; i < aLen; i++ { | |
val := f(aValue.Index(i).Interface()) | |
tmpCollection := Collection{Data: newData.Interface()} | |
if !tmpCollection.Contains(func(item interface{}) bool { | |
if reflect.TypeOf(val) != reflect.TypeOf(item) { | |
panic("Unequal types") | |
} | |
switch val.(type) { | |
case int: | |
return val.(int) == item.(int) | |
case string: | |
return val.(string) == item.(string) | |
default: | |
panic("Uncomparable data types") | |
} | |
}) { | |
newData = reflect.Append(newData, aValue.Index(i)) | |
} | |
} | |
return Collection{Data: newData.Interface()} | |
} | |
func main() { | |
a := NewCollection([]int{1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) | |
b := a. | |
// Map(func(i interface{}) interface{} { | |
// return i.(int) * 3 | |
// }). | |
// Filter(func(i interface{}) bool { | |
// return i.(int) > 6 | |
// }). | |
SortBy(func(i interface{}) interface{} { | |
return -i.(int) | |
}). | |
UniqueBy(func(i interface{}) interface{} { | |
return i | |
}) | |
// GroupBy(func(i interface{}) interface{} { | |
// if i.(int)%2 == 0 { | |
// return "even" | |
// } | |
// return "odd" | |
// }) | |
fmt.Println(b) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment