func (c MapStringInt) Reduce(cb func(string, int, interface{}) interface{}, defAgg ...interface{}) interface{} {
	var agg interface{}
	if len(defAgg) == 0 {
		agg = nil
	} else {
		agg = defAgg[0]
	}
	for k, v := range c {
		agg = cb(k, v, agg)
	}
	return agg
}
Reduce method applies a func against an accumulator and each element in the slice (from left to right) to reduce it to a single value of any type.
If no accumulator is passed as second argument, default accumulator will be nil
Returns an interface.
For asynchronicity, see ReduceAsync.
package maps
import "github.com/francoispqt/lists"
type MapStringInt map[string]int
func (c MapStringInt) Contains(s int) bool {
	for _, v := range c {
		if v == s {
			return true
		}
	}
	return false
}
func (c MapStringInt) ForEach(cb func(string, int)) {
	for k, v := range c {
		cb(k, v)
	}
}
func (c MapStringInt) Map(cb func(string, int) int) MapStringInt {
	var ret = make(map[string]int, len(c))
	for k, v := range c {
		ret[k] = cb(k, v)
	}
	return ret
}
func (c MapStringInt) MapInterface(cb func(string, int) interface{}) MapStringInterface {
	var ret = make(map[string]interface{}, len(c))
	for k, v := range c {
		ret[k] = cb(k, v)
	}
	return ret
}
func (c MapStringInt) MapAsync(cb func(string, int, chan [2]interface{}), maxConcurrency ...int) MapStringInt {
	var maxConc = lists.DEFAULT_CONC
	if len(maxConcurrency) == 1 {
		maxConc = maxConcurrency[0]
	}
	mapChan := make(chan [2]interface{}, len(c))
	ret := make(map[string]int, len(c))
	if maxConc > 0 {
		sent := 0
		received := 0
		doing := make(chan struct{}, maxConc)
		indexes := c.Indexes()
		for {
			var k string
			var v int
			if len(indexes) > sent {
				k = indexes[sent]
				v = c[k]
			}
			if len(doing) < maxConc && sent < len(c) {
				go cb(k, v, mapChan)
				sent++
				if maxConc > 0 {
					doing <- struct{}{}
				}
			} else {
				intf := <-mapChan
				received++
				if len(intf) > 1 {
					ret[intf[0].(string)] = intf[1].(int)
				} else {
					ret[intf[0].(string)] = 0
				}
				<-doing
				if received == sent {
					close(mapChan)
					return ret
				}
			}
		}
	} else {
		for k, v := range c {
			go cb(k, v, mapChan)
		}
		ct := 0
		for intf := range mapChan {
			if len(intf) > 1 {
				ret[intf[0].(string)] = intf[1].(int)
			} else {
				ret[intf[0].(string)] = 0
			}
			ct++
			if ct == len(c) {
				close(mapChan)
			}
		}
	}
	return ret
}
func (c MapStringInt) MapAsyncInterface(cb func(string, int, chan [2]interface{}), maxConcurrency ...int) MapStringInterface {
	var maxConc = lists.DEFAULT_CONC
	if len(maxConcurrency) == 1 {
		maxConc = maxConcurrency[0]
	}
	mapChan := make(chan [2]interface{}, len(c))
	ret := make(map[string]interface{}, len(c))
	if maxConc > 0 {
		sent := 0
		received := 0
		doing := make(chan struct{}, maxConc)
		indexes := c.Indexes()
		for {
			var k string
			var v int
			if len(indexes) > sent {
				k = indexes[sent]
				v = c[k]
			}
			if len(doing) < maxConc && sent < len(c) {
				go cb(k, v, mapChan)
				sent++
				if maxConc > 0 {
					doing <- struct{}{}
				}
			} else {
				intf := <-mapChan
				received++
				ret[intf[0].(string)] = intf[1]
				<-doing
				if received == sent {
					close(mapChan)
					return ret
				}
			}
		}
	} else {
		for k, v := range c {
			go cb(k, v, mapChan)
		}
		ct := 0
		for intf := range mapChan {
			ret[intf[0].(string)] = intf[1]
			ct++
			if ct == len(c) {
				close(mapChan)
			}
		}
	}
	return ret
}