lampshade
lampshade

Reputation: 3

Unique list elements in Tcl

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

Answers (1)

Donal Fellows
Donal Fellows

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

Related Questions