proc listCompare {l1 l2} {
if {[llength $l1] != [llength $l2]} { return 0}
foreach e1 $l1 e2 $l2 {
if {$e1 ne $e2} {return 0}
}
return 1
}
Is it ok/preferable to replace the element comparision with a string
representation comparison of the lists?
proc listCompare {l1 l2} {
return [expr {$l1 eq $l2}]
}
---
Related question:
To find a list in a matrix:
proc listFind {l m} {
set p 0
foreach c $m {
if {[listCompare $l $c]} { return $p }
incr p
}
return -1
}
is it possible to use lsearch:
proc listFind {l m} {
return [lsearch -exact $m $l]
}
---
Thank you for any answer,
Harald
% set m {{a b c} {1 2 3} {x y z}}
{a b c} {1 2 3} {x y z}
% set l {x y z}
x y z
% lsearch $m $l
2
rene
Of course a toplevel list comparison will be faster: a loop in C is
faster than the same in Tcl ;-)
Note though, that the result will be the same only if $l1 and $l2 are
"canonical" wrt the list representation, i.e. identical to [lrange ...
0 end].
So, to be on the safe side:
return [expr {[lrange $l1 0 end] eq [lrange $l2 0 end]}]
> Related question:
> To find a list in a matrix:
> proc listFind {l m} {
> set p 0
> foreach c $m {
> if {[listCompare $l $c]} { return $p }
> incr p
> }
> return -1}
>
> is it possible to use lsearch:
> proc listFind {l m} {
> return [lsearch -exact $m $l]}
Through the same reasoning, you'll see that this will work only if you
arrange for the sublists themselves to be stored in canonical form.
A good thing would be to build your program so that the hypothesis
always holds:
- canonize when coming from user input (with [lrange])
- then only manipulate through list operations
Note that the above strategy will be much faster than sticking [lrange
0 end] blindly everywhere...
-Alex
For all "normal" lists, expr {$l1 eq $l2} will be most likely faster.
However, for some special lists, like:
set l1 [lrepeat 1000000 [lrepeat 1000000 "foo"]]
set l2 [lrepeat 1000000 [lrepeat 1000000 "foo"]]
whose string-representation would exceed the available memory on contemporary
machines, your explicit algorithm still works, while "eq" attempts to convert
both to strings and thereby breaks the interpreter. :-)
There may exist other patterns of lists where iterating a list in tcl-code
is still faster than converting those lists to strings, but I claim
that these aren't very common, either.
Thank you all.
Anyway, the issue with the canonical is already helpful.
I feared, there might be some issues also with native numbers etc.
In general, I don't like to use the string representation, but
specially a
lsearch looks so much nicer than two nested loops. And if it is
"save", so what ?
Speed is always a funny thing anyway ;-)
I would love to have such native commands, well the wishlist is long
as usual...
Thank you,
Harald
proc listFind {l m} {
set p 0
set l [lassign $l f]
while {-1 != [set p [lsearch -exact -start $p -index 0 $m $f]]} {
if {[listCompare $l [lrange [lindex $m $p] 1 end]]} { return