interleave

AMG I had a list of keys that I wanted to insert into an array, with all the values set to "". So I wrote this proc to help me:

 proc interleave {args} {
     if {[llength $args] == 0} {return {}}

     set data {}
     set idx  0
     set head {}
     set body "lappend data"

     foreach arg $args {
         lappend head v$idx $arg
         append  body " \$v$idx"
         incr idx
     }

     eval foreach $head [list $body]
     return $data
 }

But I made it pretty general--- it can handle any number of args, also arguments with unequal lengths. Check it:

 % set keys {one two three four  }
 % set vals {uno dos tres  cuatro}
 % array set numbers [interleave $keys $vals]
 % parray numbers
 numbers(four)  = cuatro
 numbers(one)   = uno
 numbers(three) = tres
 numbers(two)   = dos

 % interleave {a1 a2 a3 a4} {b1 b2 b3 b4} {c1 c2 c3 c4} {d1 d2 d3 d4}
 a1 b1 c1 d1 a2 b2 c2 d2 a3 b3 c3 d3 a4 b4 c4 d4

 % set elems {when 900 years old you reach look as good you will not}
 % array set my_set [interleave $elems {}]
 % array names my_set
 will as years not good look you 900 when reach old

With {*} I should be able to change that second-to-last line to simply "foreach {*}$head $body".


MAKR 2009-04-09 a simpler implementation that is zipping two lists can be found at [lzip].