Updated 2017-02-09 14:30:21 by zashi

SS 30Nov2004: The following commands are basic set operations for Tcl lists. They are part of a larger library for functional programming in Tcl that's possible to find at [1]. The proposed commands try to run in O(M+N) time complexity, and to don't mess with the order of the elements when possible.
``` proc lintersect {a b} {
foreach e \$a {
set x(\$e) {}
}
set result {}
foreach e \$b {
if {[info exists x(\$e)]} {
lappend result \$e
}
}
return \$result
}

proc lunion {a b} {
foreach e \$a {
set x(\$e) {}
}
foreach e \$b {
if {![info exists x(\$e)]} {
lappend a \$e
}
}
return \$a
}

proc ldifference {a b} {
foreach e \$b {
set x(\$e) {}
}
set result {}
foreach e \$a {
if {![info exists x(\$e)]} {
lappend result \$e
}
}
return \$result
}

proc in {list element} {
expr {[lsearch -exact \$list \$element] != -1}
}```

MJ - Using 8.5 ni and in, this can be speeded up quite considerable, for instance:
``` proc ldifference2 {a b} {
set result {}
foreach e \$a {
if {\$e ni \$b} {lappend result \$e}
}
return \$result
}```

[zashi] - The above example using ni doesn't work if \$b has more elements than \$a. APN I think you are confusing the difference operation. It returns A-B, i.e. all elements of A that are not also in B. It is not "all values that are in A or B but not both".

You can also use lmap to make this more concise. But then to fix the length issue it gets bigger again
```  proc ldifference3  {a b} {
if {[llength \$a] > [llength \$b]} {
return [lmap e \$a {if {\$e ni \$b} {set e} else continue}]
} else {
return [lmap e \$b {if {\$e ni \$a} {set e} else continue}]
}
}
```