Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

When is it ok to compare lists with "eq"

98 views
Skip to first unread message

Harald Oehlmann

unread,
Aug 23, 2010, 8:19:54 AM8/23/10
to
I want to check if the elements of two lists are identical strings:

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

rene

unread,
Aug 23, 2010, 8:55:20 AM8/23/10
to
you can use lsearch like:

% 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

Alexandre Ferrieux

unread,
Aug 23, 2010, 9:02:57 AM8/23/10
to
On Aug 23, 2:19 pm, Harald Oehlmann <wortka...@yahoo.de> wrote:
> I want to check if the elements of two lists are identical strings:
>
> 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}]}

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

Harald Oehlmann

unread,
Aug 23, 2010, 9:48:09 AM8/23/10
to
Thank you for the answer, very helpful !
Harald

Andreas Leitgeb

unread,
Aug 23, 2010, 12:14:02 PM8/23/10
to
Harald Oehlmann <wort...@yahoo.de> wrote:
> I want to check if the elements of two lists are identical strings:
> 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}]
> }

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.

Harald Oehlmann

unread,
Aug 23, 2010, 12:40:22 PM8/23/10
to
On 23 Aug., 18:14, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:

> 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

Harald Oehlmann

unread,
Aug 24, 2010, 2:34:26 AM8/24/10
to
To find a list within a matrix without using the string
representation,
one may also search the first element with lsearch and then compare
the remaining elements:

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

0 new messages