Reputation: 3
I have two Tcl lists of equal length, u
and v
. Many of the entries in u
are known to be identical. For every unique entry in u
, I would like to average over the corresponding entries in v
. So, if my lists are {1 2 1 2}
and {1 2 3 4}
, the output should be {1 2}
(only the unique entries in u
), and {2 3}
, where 2 comes from (1+3)/2
, and 3 comes from (2+4)/2
.
I have tried the following:
set unique [lsort -unique $u]
foreach i $unique {
set ave 0; set N 0
foreach j $u k $v {
if {$i == $j} {set ave [expr {$ave+$k}]}
}
lappend w [expr {$ave/$N}]
}
This works, but it is far too slow for larger lists. Does anyone know a more efficient way of doing this?
Thanks in advance!
Upvotes: 0
Views: 210
Reputation: 137567
I would use a dictionary to accumulate values in groups by unique keys. This would do pretty much the entire process for me (together with a bit of post-processing to get the averages).
foreach a $u b $v {
dict lappend collector $a $b
}
set uniques [dict keys $collector]
set averages [lmap items [dict values $collector] {
expr { [tcl::mathop::+ {*}$items] / double([llength $items]) }
}
The averages are naturally floating point values.
Upvotes: 1