package exchangeUtility import ( "sort" ) const ( Mean string = "Mean" Median string = "Median" Mode string = "Mode" Min string = "Min" Max string = "Max" ) type AggregateDailyToMonthly struct { AggregatedNumbers []float64 } func (mm *AggregateDailyToMonthly) CalcValue(avgMethod string) float64 { switch avgMethod { case Mean: return mm.CalcMean() case Median: return mm.CalcMedian() case Mode: return mm.CalcMode() case Max: return mm.GetMaxValue() case Min: return mm.GetMinValue() } return 0 } // return the minimum value func (mm *AggregateDailyToMonthly) GetMinValue() float64 { sort.Float64s(mm.AggregatedNumbers) // sort the numbers return mm.AggregatedNumbers[0] } // return the maximum value func (mm *AggregateDailyToMonthly) GetMaxValue() float64 { sort.Float64s(mm.AggregatedNumbers) // sort the numbers return mm.AggregatedNumbers[len(mm.AggregatedNumbers)-1] } // calculate and return mode func (mm *AggregateDailyToMonthly) CalcMode() float64 { var modes []float64 frequencies := make(map[float64]int, len(mm.AggregatedNumbers)) highestFrequency := 0 for _, x := range mm.AggregatedNumbers { frequencies[x]++ if frequencies[x] > highestFrequency { highestFrequency = frequencies[x] } } for x, frequency := range frequencies { if frequency == highestFrequency { modes = append(modes, x) } } if highestFrequency == 1 || len(modes) == len(mm.AggregatedNumbers) { modes = modes[:0] // Or: modes = []float64{} } sort.Float64s(modes) mm.AggregatedNumbers = modes return mm.CalcMean() } // calculate the range values // last value - first value func (mm *AggregateDailyToMonthly) CalcRangeValues() float64 { sort.Float64s(mm.AggregatedNumbers) // sort the numbers return mm.GetMaxValue() - mm.GetMinValue() } // calculate the "mean" value // sum of all the values // divided by its quantity func (mm *AggregateDailyToMonthly) CalcMean() float64 { total := 0.0 for _, v := range mm.AggregatedNumbers { total += v } return total / float64(len(mm.AggregatedNumbers)) } // calculate the "median" value // if the total of numbers is odd // takes the middle value // // if the total of numbers is even // calculate the "mean" of the middle two values func (mm *AggregateDailyToMonthly) CalcMedian() float64 { sort.Float64s(mm.AggregatedNumbers) // sort the numbers mNumber := len(mm.AggregatedNumbers) / 2 if mm.IsOdd() { return mm.AggregatedNumbers[mNumber] } return (mm.AggregatedNumbers[mNumber-1] + mm.AggregatedNumbers[mNumber]) / 2 } // check if the total of numbers is // odd or even func (mm *AggregateDailyToMonthly) IsOdd() bool { if len(mm.AggregatedNumbers)%2 == 0 { return false } return true }