func CountBy(seq Seq, cb Callback) (result map[string]int) {
	result = make(map[string]int, 0)
	key := ""
	if seq == nil || cb == nil {
		return result
	}
	for index, val := range seq {
		key = cb(val, index, seq).(string)
		if result[key] == 0 {
			result[key] = 1
		} else {
			result[key] = result[key] + 1
		}
	}
	return result
}
CountBy returns map, which values are count of certain kind of values,
and keys are names of this kinds
package ugo
import (
	sorter "github.com/alxrm/ugo/timsort"
	"math"
	"math/rand"
	"reflect"
	"time"
)
type Object interface{}
type Seq []interface{}
type Collector func(memo, current, currentKey, src Object) Object
type Callback func(current, currentKey, src Object) Object
type Comparator func(left, right Object) int
type Predicate func(current, currentKey, src Object) bool
type Action func(current, currentKey, src Object)
const (
	toMin int = -1  
	toMax int = 1   
)
const (
	less   = -1
	equal  = 0
	larger = 1
)
func Chain(target Seq) *ChainWrapper {
	if IsEmpty(target) {
		target = Seq{}
	}
	return &ChainWrapper{Mid: target, Res: target}
}
func NewSeq(size int) Seq {
	return make(Seq, size)
}
func Each(seq Seq, cb Action) {
	if cb == nil {
		return
	}
	for index, val := range seq {
		cb(val, index, seq)
	}
}
func ForEach(seq Seq, cb Action) {
	Each(seq, cb)
}
func Map(seq Seq, cb Callback) Seq {
	if seq == nil {
		return Seq{}
	}
	if cb == nil {
		return seq
	}
	length := len(seq)
	result := NewSeq(length)
	for index, val := range seq {
		result[index] = cb(val, index, seq)
	}
	return result
}
func Collect(seq Seq, cb Callback) Seq {
	return Map(seq, cb)
}
func Filter(seq Seq, cb Predicate) Seq {
	if seq == nil {
		return Seq{}
	}
	if cb == nil {
		return seq
	}
	result := NewSeq(0)
	for index, val := range seq {
		if cb(val, index, seq) {
			result = append(result, val)
		}
	}
	return result
}
func Select(seq Seq, cb Predicate) Seq {
	return Filter(seq, cb)
}
func Reject(seq Seq, cb Predicate) Seq {
	if seq == nil {
		return Seq{}
	}
	if cb == nil {
		return seq
	}
	return Filter(seq, negate(cb))
}
func Reduce(seq Seq, cb Collector, initial Object) Object {
	var memo Object
	if IsEmpty(seq) || cb == nil {
		return nil
	}
	length := len(seq) - 1
	if initial == nil {
		memo = seq[0]
		return createReduce(seq, cb, memo, 1, toMax, length-1)
	}
	memo = initial
	return createReduce(seq, cb, memo, 0, toMax, length)
}
func Inject(seq Seq, cb Collector, initial Object) Object {
	return Reduce(seq, cb, initial)
}
func FoldL(seq Seq, cb Collector, initial Object) Object {
	return Reduce(seq, cb, initial)
}
func ReduceRight(seq Seq, cb Collector, initial Object) Object {
	var memo Object
	if IsEmpty(seq) || cb == nil {
		return nil
	}
	length := len(seq) - 1
	if initial == nil {
		memo = seq[length]
		return createReduce(seq, cb, memo, length-1, toMin, length-1)
	}
	memo = initial
	return createReduce(seq, cb, memo, length, toMin, length)
}
func FoldR(seq Seq, cb Collector, initial Object) Object {
	return ReduceRight(seq, cb, initial)
}
func Min(seq Seq, cb Comparator) Object {
	return createComparingIterator(seq, cb, toMin, len(seq))
}
func Max(seq Seq, cb Comparator) Object {
	return createComparingIterator(seq, cb, toMax, len(seq))
}
func Find(seq Seq, cb Predicate) Object {
	length := len(seq) - 1
	res, _ := createPredicateSearch(seq, cb, 0, toMax, length)
	return res
}
func Detect(seq Seq, cb Predicate) Object {
	return Find(seq, cb)
}
func FindLast(seq Seq, cb Predicate) Object {
	length := len(seq) - 1
	res, _ := createPredicateSearch(seq, cb, length, toMin, length)
	return res
}
func FindIndex(seq Seq, cb Predicate) int {
	length := len(seq) - 1
	_, index := createPredicateSearch(seq, cb, 0, toMax, length)
	return index
}
func FindLastIndex(seq Seq, cb Predicate) int {
	length := len(seq) - 1
	_, index := createPredicateSearch(seq, cb, length, toMin, length)
	return index
}
func Some(seq Seq, cb Predicate) bool {
	return FindIndex(seq, cb) != -1
}
func Any(seq Seq, cb Predicate) bool {
	return Some(seq, cb)
}
func IndexOf(seq Seq, target Object, isSorted bool, cb Comparator) int {
	if cb == nil {
		return -1
	}
	if isSorted {
		return createBinarySearch(seq, target, cb, len(seq))
	}
	equalityPredicate := func(cur, _, _ Object) bool { return cb(cur, target) == 0 }
	return FindIndex(seq, equalityPredicate)
}
func LastIndexOf(seq Seq, target Object, cb Comparator) int {
	if cb == nil {
		return -1
	}
	var equalityPredicate Predicate = func(cur, _, _ Object) bool { return cb(cur, target) == 0 }
	return FindLastIndex(seq, equalityPredicate)
}
func Contains(seq Seq, target Object, isSorted bool, cb Comparator) bool {
	if cb == nil {
		return false
	}
	return IndexOf(seq, target, isSorted, cb) != -1
}
func Includes(seq Seq, target Object, isSorted bool, cb Comparator) bool {
	return Contains(seq, target, isSorted, cb)
}
func Every(seq Seq, cb Predicate) bool {
	if IsEmpty(seq) || cb == nil {
		return false
	}
	for index, val := range seq {
		if !cb(val, index, seq) {
			return false
		}
	}
	return true
}
func All(seq Seq, cb Predicate) bool {
	return Every(seq, cb)
}
func Uniq(seq Seq, cb Comparator) Seq {
	if seq == nil {
		return Seq{}
	}
	if cb == nil {
		return seq
	}
	result := NewSeq(0)
	for _, value := range seq {
		if !Contains(result, value, false, cb) {
			result = append(result, value)
		}
	}
	return result
}
func Unique(seq Seq, cb Comparator) Seq {
	return Uniq(seq, cb)
}
func Difference(seq, other Seq, cb Comparator) Seq {
	if seq == nil {
		return Seq{}
	}
	if cb == nil || other == nil {
		return Seq{}
	}
	result := NewSeq(0)
	for _, value := range seq {
		if !Contains(other, value, false, cb) {
			result = append(result, value)
		}
	}
	return result
}
func Without(seq Seq, nonGrata Object, cb Comparator) Seq {
	if seq == nil || cb == nil {
		return Seq{}
	}
	if nonGrata == nil {
		return seq
	}
	result := NewSeq(0)
	for _, value := range seq {
		if cb(value, nonGrata) != 0 {
			result = append(result, value)
		}
	}
	return result
}
func Intersection(seq, other Seq, cb Comparator) Seq {
	if seq == nil {
		return Seq{}
	}
	if cb == nil || other == nil {
		return Seq{}
	}
	result := NewSeq(0)
	for _, value := range seq {
		if Contains(other, value, false, cb) {
			result = append(result, value)
		}
	}
	return Uniq(result, cb)
}
func Union(seq, other Seq, cb Comparator) Seq {
	if seq == nil {
		return Seq{}
	}
	if cb == nil {
		return Seq{}
	}
	result := Concat(seq, other)
	return Uniq(result, cb)
}
func SortBy(seq Seq, cb Comparator) Seq {
	if seq == nil {
		return Seq{}
	}
	if cb == nil {
		return seq
	}
	sorter.Sort(seq, lessThan(cb))
	return seq
}