Purpose: Definition and discussion of set functionality, especially the function to compute the difference of two sets. Difference being the set containing those elements which are in the first set but not the second.
Back to the Chart of proposed set functionality.
Arguments:
Result:
Implementation:
Several variants are possible:
Shortcuts to use in the code:
Timing:
Summary:
Variant A.
proc ::setops::diff {a b} { if {[llength $a] == 0} { return {} } if {[llength $b] == 0} { return $a } set res {} set a [lsort $a] set b [lsort $b] while {1} { # Store lindex/0,1 in var, access later faster ? set n [string compare [lindex $a 0] [lindex $b 0]] if {$n == 0} { # A = B => element in both, so not in difference set a [lrange $a 1 end] set b [lrange $b 1 end] } elseif {$n > 0} { # A > B, remove B, we are beyond the element. set b [lrange $b 1 end] } else { # A < B, remove A, we are beyond the element. # This element in A is part of the result too. lappend res [lindex $a 0] set a [lrange $a 1 end] } if {[llength $a] == 0} { return $res } if {[llength $b] == 0} { foreach e $a { lappend res $a } return $res } } return $res }
Variant B.
proc ::setops::diff {a b} { if {[llength $a] == 0} { return {} } if {[llength $b] == 0} { return $a } set res {} foreach e $b { set ba($e) . } foreach e $a { if {![info exists ba($e)]} { lappend res $e } } return $res }
Variant C.
proc ::setops::diff {a b} { if {[llength $a] == 0} { return {} } if {[llength $b] == 0} { return $a } set res {} foreach $b {.} {break} foreach e $a { if {![info exists $e]} { lappend res $e } } return $res }
-- AK