## Numeric Statistics From a List

Created by CecilWesterhof.

At a certain point I needed the maximum, minimum and mean of a list. Instead of calculating them one after the other I created a proc that calculates everything in one go. And also length and sum. (But KPV pointed out that there is ::math::statistics::basic-stats . So I do not need this any-more.

This is the proc:

```proc listNumericStats thisList {
set length [llength \$thisList]
if {\$length == 0} {
error "List cannot be empty"
}
set max [lindex \$thisList 0]
set min \$max
set sum 0.
foreach element \$thisList {
set sum [expr {\$sum + \$element}]
if {\$element < \$min} {
set min \$element
} elseif {\$element > \$max} {
set max \$element
}
}
dict set stats length \$length
dict set stats max    \$max
dict set stats mean   [expr {\$sum / \$length}]
dict set stats min    \$min
dict set stats sum    \$sum
return \$stats
}```

DEC:That sounds over kill to me

```set aList [ lsort -real \$anotherList]
set max [ lindex \$aList end]
set min [ lindex \$aList 0]
set sum [expr {[join \$aList "+"]}]
set len [llength \$aList ]
set mean [ expr {\$sum/\$len}]```

DEC:I would avoid looping over a list at the script level if you can

CecilWesterhof: With your code you loop two times over the list instead of once. And you need a sort also, which is also not cheap for big lists. So I would think that my implementation is a lot more efficient.

But it is moot, because I do not need it any-more thanks to KPV.

KPV: Also checkout ::math::statistics::basic-stats

2018-08-26: Never assume.

```interp alias {} listNumericStatsA {} listNumericStats

proc listNumericStatsB thisList {
set aList [ lsort -real \$thisList]
set sum [expr [join \$aList "+"]]
dict set stats length [llength \$aList]
dict set stats max    [lindex \$aList end]
dict set stats mean   [expr {\$sum/[llength \$aList]}]
dict set stats min    [lindex \$aList 0]
dict set stats sum    \$sum
return \$stats
}

proc listNumericStatsC thisList {
set sum [::tcl::mathop::+ {*}\$thisList]
dict set stats length [llength \$thisList]
dict set stats max    [::tcl::mathfunc::max {*}\$thisList]
dict set stats mean   [expr {\$sum/[llength \$thisList]}]
dict set stats min    [::tcl::mathfunc::min {*}\$thisList]
dict set stats sum    \$sum
return \$stats
}

package require math
set theList [lmap item [lrepeat 300 *] {::math::random}]

puts [expr {[listNumericStatsA \$theList] eq [listNumericStatsB \$theList] && [listNumericStatsA \$theList] eq [listNumericStatsC \$theList]}]
puts [expr {[listNumericStatsA \$theList] eq [listNumericStatsC \$theList]}]

time {listNumericStatsA \$theList} 10000
time {listNumericStatsB \$theList} 10000
time {listNumericStatsC \$theList} 10000```
```0
1
102.5553 microseconds per iteration
956.2068 microseconds per iteration
367.4345 microseconds per iteration```