I have matrix of 10 rows and 10 column. I want to crate tcl list where each element of list will be 2 numbers..1 from each row.
e.g if My matrix is
$a $b $c $d $e
$f $g $h $i $j
$k $l $m $n $o
$p $q $r $s $t
I want to have list that contain elements $a $b, $f $g, $k $l, $p $q.
Can someone tell me how to do this ?
Assuming your matrix is a list of lists, you can use the lmap command:
$ tclsh
% set matrix {
{a b c d e}
{f g h i j}
{k l m n o}
{p q r s t}
}
{a b c d e}
{f g h i j}
{k l m n o}
{p q r s t}
% lmap sublist $matrix {lrange $sublist 0 1}
{a b} {f g} {k l} {p q}
If you are using a matrix as defined by the struct::matrix package in Tcllib, you do this:
set pairlist [$matrix get rect 0 0 1 end]
Notes: the name of the matrix is in the matrix variable, rect is short for “rectangle”, the 0 0 give the coordinates in the matrix of the top-left corner of the rectangle to extract, and 1 end gives the coordinates in the matrix of the bottom right corner of the rectangle (matrices support end to mean the last row and/or column, just like Tcl strings and lists).
package require struct::matrix
struct::matrix data
data add columns 5
data add rows 4
data set rect 0 0 {
{a b c d e}
{f g h i j}
{k l m n o}
{p q r s t}
}
data get rect 0 0 1 end
# {a b} {f g} {k l} {p q}
This should produce the results
Related
I have 2 lists with some identical elements, and I want to remove these elements between these 2 lists; Example would be like this:
set list_1 [list a b c d]
set list_2 [list e f b a]
puts $list_1_remove_identical ; #Output that I want
c d
puts $list_2_remove_identical ;
e f
You can use a dict to store the elements of one list for fast lookup to see if they're present in the other list, and only keep the ones that aren't:
#!/usr/bin/env tclsh
proc list_difference {a b} {
set in_b [dict create]
foreach elem $b {
dict set in_b $elem 1
}
lmap elem $a { if {[dict exists $in_b $elem]} { continue } else { set elem } }
}
set list_1 [list a b c d]
set list_2 [list e f b a]
puts [list_difference $list_1 $list_2] ;# c d
puts [list_difference $list_2 $list_1] ;# e f
As Donal points out correctly, it depends on the nature of the two lists to be compared. For example, if you are looking at sets (no duplicates, ordering not relevant), then you might use tcllib's struct::set:
% package req struct
2.1
% set list_1 [list a b c d]
a b c d
% set list_2 [list e f b a]
e f b a
% struct::set difference $list_1 $list_2
d c
% struct::set difference $list_2 $list_1
e f
You can use the in operator to check for each element if it exists in the other list:
puts [lmap n $list_1 {if {$n in $list_2} continue;set n}]
puts [lmap n $list_2 {if {$n in $list_1} continue;set n}]
I have a procedure that returns a list of lists. I can't figure out how to access the inner lists without splitting them first. I'm sure there must be a cleaner way.
For example, this:
proc return_l_of_l {} {
set x {a b c}
set y {d e f}
return [list [list $x] [list $y]]
}
set l [return_l_of_l]
set x_list [lindex $l 0]
set y_list [lindex $l 1]
foreach x $x_list { puts $x }
foreach y $y_list { puts $y }
outputs:
a b c
d e f
not:
a
b
c
d
e
f
The problem is this line:
return [list [list $x] [list $y]]
Since x and y already hold lists, it makes a list of lists of lists. You should instead do:
return [list $x $y]
or possibly:
return [list [list {*}$x] [list {*}$y]]
proc return_l_of_l {} {
set x {a b c}
set y {d e f}
return [list [list $x] [list $y]]
}
returns a list of two lists each consisting of a single element — a b c and d e f. That's because {a b c} and {d e f} are already constructs which can be interpreted as lists.
Supposedly you'd just need
return [list $x $y]
Say I have a list, a b c b b d e e f …, and I don't know how many different kind of elements are in there.
How do I count the number of each unique element and print them out?
Output would looks like:
a: 32
b: 12
c: 6
…
You have to count them up. This isn't too hard with an array or dictionary of counters. I'll use a dictionary since then they'll be printed in order of first occurrence. (With an array, you'd get a “random” order or you'd have to sort them.)
set counters {}
foreach item $list {
dict incr counters $item
}
dict for {item count} $counters {
puts "${item}: $count"
}
Try this if you have 8.4 or older version of TCL,
set lst "a a a a b b b c c c d d a a a f f f f f s s s s"
set unique [lsort -unique $lst]
foreach f $unique {
set cnt 0
foreach item $lst {
if {$item == $f} {
incr cnt
}
}
puts "$f :: $cnt"
}
Gives Output Like,
% tclsh main.tcl
a :: 7
b :: 3
c :: 3
d :: 2
f :: 5
s :: 4
It can be easily done using lsearch and llength.
Lets say your list is {a c a c s a a c a} then,
set tempList {a c a c s a a c a}
puts "c : [llength [lsearch -all $tempList c]]"
puts "a : [llength [lsearch -all $tempList a]]"
puts "d : [llength [lsearch -all $tempList d]]"
Output :
c : 3
a : 5
d : 0
Explanation : lsearch -all, will return all the index of matching element
and this list of index is returned to llength which will count length of the list.
The dict or array solution is the best one and should be preferred. Another way that works on a sorted list of tokens is to match contiguous regions of non-blank tokens.
% regexp -all -inline {(\S+)(?:\s+\1)*} {a a b b b c d d}
{a a} a {b b b} b c c {d d} d
The result is an even-sized list of alternately matched regions of tokens and the token matched in the region. This can be used to print a frequency report for the tokens in the list in list.
foreach {a b} [regexp -all -inline {(\S+)(?:\s+\1)*} [lsort $list]] {
puts "$b: [llength $a]"
}
Note the limitation that the tokens cannot contain blanks. This can be overcome, but it's simpler to use the array / dict solution which only requires the tokens to be valid list elements.
Documentation: foreach, llength, lsort, puts, Syntax of Tcl regular expressions, regexp
I need to calculate a Cartesian product of two lists.
My list contains large number of elements, so nested foreach is not a good idea in my case.
Anything else, that can be used there?
You might be able to work on the values while it's being put together. It's hard to say without at least a snapshot of the structure you're working with. Here's a simple example.
The proc doesn't return a matrix it does work on points in the matrix.
proc my_cartesian {a b} {
set len_a [llength $a]
set len_b [llength $b]
set len [expr $len_a * $len_b]
set y 0
for {set i 0} {$i < $len} {incr i} {
set x [expr $i % $len_a]
if {$x == 0 && $i != 0} {
incr y
}
set px [lindex $a $x]
set py [lindex $b $y]
# Your code
puts "$px, $py"
}
}
my_cartesian {a b c} {1 2 3}
output:
a, 1
b, 1
c, 1
a, 2
b, 2
c, 2
a, 3
b, 3
c, 3
In tcl I need to execute a script for each possible combination of values of an unknown number of variables.
Describing it in words:
A goes from a0 -> a1 with steps of "da"
B goes from b0 -> b1 with steps of "db"
C goes from c0 -> c1 with steps of "dc"
....
The number of variables can vary. Note: The names of the variables are not known beforehand, 'A' could also be called 'Ape' or anything else. Same goes for the other variables.
What I have so far is:
array set min_vals {A $a0 B $b0 C $c0 ...} ;# --> These are user-defined
array set max_vals {A $a1 B $b1 C $c1 ...} ;# --> These are user-defined
array set step_vals {A $da B $db C $dc ...} ;# --> These are user-defined
# First I determine the number of variables and the number of values they can have
set nr_vars [array size min_vals] ;# Determine nr of variables
set nr_vals [list] ;# --> Set empty list for nr of values for each variable
foreach var_name [array names min_vals] {
set nr [expr {round( ( $max_vals(${var_name})-$min_vals(${var_name}) ) / $step_vals(${var_names}) )}]
set nr_vals [concat $nr_vals $nr]
}
Now I need to somehow loop through each possible combination:
[A=a0, B=b0, C=c0]
[A=a0+da, B=b0, C=c0]
[A=a0+2*da, B=b0, C=c0]
...
...
[A=a1, B=b0, C=c0]
[A=a0, B=b0+db, C=c0]
[A=a0+da, B=b0+db, C=c0]
...
...
[A=a1, B=b1, C=c1]
I hope there is an easy way to do this. The only way I could think of doing this was by having a single loop with number of iterations containing all combinations and let each iteration-number correspond to a specific combination. But I'm sure there must be a less cumbersome way.
_
Edit:
Maybe I wasn't really clear about what I exactly wanted. I don't care about the actual output. My aim is to set each variable to the correct value and run another script with these variables:
set A $a0
set B $b0
set C $c0
source run/some/script.tcl
And repeat this for each possible combination of values of A, B and C.
Use nested for loops
for {set a $min_vals(A)} {$a <= $max_vals(A)} {incr a $step_vals(A)} {
for {set b $min_vals(B)} {$b <= $max_vals(B)} {incr b $step_vals(B)} {
for {set c $min_vals(C)} {$c <= $max_vals(C)} {incr c $step_vals(C)} {
do something with [list $a $b $c]
}
}
}
Ah, needs to be more dynamic. Hmmm,
set variables {A B C}
array set min_vals {A 1 B 10 C 100}
array set max_vals {A 3 B 30 C 300}
array set step_vals {A 1 B 10 C 100}
proc build_loops {} {
global variables
# create the "seed" code: what to do with the generated tuple
set code "do_something_with \[list "
foreach var $variables {
append code "\$[loop_var $var] "
}
append code "]"
# and wrap layers of for loops around the seed
foreach var [lreverse $variables] {
set loop_var [loop_var $var]
set code [format {for {set %s $min_vals(%s)} {$%s <= $max_vals(%s)} {incr %s $step_vals(%s)} {%s}} \
$loop_var $var \
$loop_var $var \
$loop_var $var \
$code \
]
}
return $code
}
proc loop_var {varname} {
return "loop_[string tolower $varname]"
}
proc do_something_with {args} {
puts $args
}
set code [build_loops]
puts $code
eval $code
for {set loop_a $min_vals(A)} {$loop_a <= $max_vals(A)} {incr loop_a $step_vals(A)} {for {set loop_b $min_vals(B)} {$loop_b <= $max_vals(B)} {incr loop_b $step_vals(B)} {for {set loop_c $min_vals(C)} {$loop_c <= $max_vals(C)} {incr loop_c $step_vals(C)} {do_something_with [list $loop_a $loop_b $loop_c ]}}}
{1 10 100}
{1 10 200}
{1 10 300}
{1 20 100}
{1 20 200}
{1 20 300}
{1 30 100}
{1 30 200}
{1 30 300}
{2 10 100}
{2 10 200}
{2 10 300}
{2 20 100}
{2 20 200}
{2 20 300}
{2 30 100}
{2 30 200}
{2 30 300}
{3 10 100}
{3 10 200}
{3 10 300}
{3 20 100}
{3 20 200}
{3 20 300}
{3 30 100}
{3 30 200}
{3 30 300}
I keep a separate list of the variable names: [array names a] returns an unordered list of names, and (I assume) it is important to know the order of the tuple given to the do_something_with proc