WJG (16/Feb/06) A simple proc to compare the contents of two lists. It returns a list equal to the differences.
#---------------- # compare list a with b #---------------- proc listcomp {a b} { set diff {} foreach i $a { if {[lsearch -exact $b $i]==-1} { lappend diff $i } } return $diff } catch {console show} set a {1 2 3 4 5 6} set b {2 4 6 8} puts "list a = \{$a\}\nlist b = \{$b\}\nThe difference between a and b is \{[listcomp $a $b]\}."
male - 2006-02-16: reading the title I thought about something like "string compare".
So what's about this approach of a kind of list compare lcompare:
proc lcompare {list1 list2} { set length1 [llength $list1]; set length2 [llength $list2]; if {$length1 < $length2} { return [expr {double(-1)}]; } elseif {$length1 > $length2} { return [expr {double(1)}]; } if {[lindex $list1 0] eq $list1} { return [expr {double([string compare $list1 $list2])}]; } set result [expr {double(0)}]; foreach element1 $list1 element2 $list2 { set result [expr {$result + [lcompare $element1 $element2]}]; } return [expr {$result / $length1}]; }
WJG (16/Feb/06) male, what is this proc supposed to do?
male - 2006-02-16: sorry I didn't explain it.
lcompare returns a number between -1 and 1 to tell if the list1 is "lower" or "greater" than list2 - like in string compare.
It is about comparing each atom of a list or sub lists with string compare. The results are summed and diveded by the count of compared atoms. I assumed this as one way to do this. Perhaps this is the wrong way!
WJG (16/Feb/06) I fancied that the idea was to provide a simple decision. Running my clip above gives away the purpose. Its simply to compare one list with the other and then to return the differences.
jcw - The way the original was written, it really is sort of a "minus" or "except" set operator.
(Exercise for the reader: fix the error when this is given two identical lists)
AK Feb 16, 2006: Tcllib's struct module has a package struct::set with all kinds of set operators. The original listcomp is simply struct::set difference.
KBK 2007-11-20 The "difference between two lists" is a trifle ambiguous. If the lists do indeed represent sets of items, then struct::set difference is what you want. If the lists are, say, lines from two versions of a file, and you want to find the difference the way the diff command does, then you're probably after struct::list longestCommonSubsequence (The struct::list lcsInvert call repackages the results of longestCommonSubsequence' in a more convenient form.) See also diff in Tcl.
See also: Additional list functions