Updated 2015-02-19 10:25:57 by PeterLewerin

Peter Lewerin (content disclaimer) 2013-12-31: Find the difference of two lists, i.e. the list of elements that occur in list a but not in list b (and not the inverse of the intersection, i.e. the list of elements that occur in either one of the two lists but not in the other).
package require Tcl 8.5
proc ldiff {a b} {
    lmap elem $a { expr {$elem in $b ? [continue] : $elem} }
}

ldiff {2 3 4 5 6 7 8 9 10} {2 3 5 7}
# -> 4 6 8 9 10
ldiff {1 2 3} {2 3 4}
# -> 1

This implementation probably isn't very efficient, but there you go.

Guys? No one else seems to care about this operation. It's not mentioned anywhere else on the wiki (yet, I'm going to add it to a couple of pages where I think it fits); it's not one of the listx functions. Don't you ever need to remove one set of elements from another? I use this command all the time!

Gotta move with the times, it's not 2007 anymore!

The "new" in operator is more expressive than lsearch -exact, and, as I found today (2014-01-21), quite a bit faster. So my old implementation gets retired (but I'll leave it here a while for pre-8.5 Tclers).
proc ldiff {a b} {
    lmap elem $a {
        expr {[lsearch -exact $b $elem] > -1 ? [continue] : $elem}
    }
}

Note that you might need a replacement for lmap as well if you don't have Tcl 8.6. I've added a couple of implementations that ought to work with 8.5 and 8.4 on the lmap page (open the first discussion block and scroll down a bit, look for the signature "PL". There are a couple of other implementations that look like they ought to work for ldiff too, at least RS's solution).

gkubu - 2013-12-31 17:15:58

see also struct::set, http://tcllib.sourceforge.net/doc/struct_set.html (subcommand difference)