Reputation: 39
proc ListComp { List1 List2 } {
set DiffList {}
foreach Item $List1 {
if { [ lsearch -exact $List2 $Item ] == -1 } {
lappend DiffList $Item
}
}
foreach Item $List2 {
if { [ lsearch -exact $List1 $Item ] == -1 } {
if { [ lsearch -exact $DiffList $Item ] == -1 } {
lappend DiffList $Item
}
}
}
return $DiffList
}
set diff [Listcomp $list1 $list2]
puts diff
Input:
list1 {red, yellow, green, blue, orange}
list2 {red, green, blue, orange}
expected output: yellow
output received:
yellow green
green blue
blue orange
orange
The search and match should be either ways. if length of list1 > list2, the extra element in list1 should be printed. if length of list1 < list2, the omitted element in list1 should be printed
Upvotes: 1
Views: 3785
Reputation: 137807
In general, each list could have elements that the other does not. The best approach is therefore to compute two result lists at the same time, being the elements present in one list that are absent in the other and vice versa. Then it's up to you to decide what to do with the information.
proc ComputeUniques {listA listB} {
set A {}
set B {}
foreach a $listA {
dict set A $a 0; # The 0 is just an arbitrary value
}
foreach b $listB {
dict set B $b 0
dict unset A $b
}
foreach a $listA {
dict unset B $a
}
return [list [dict keys $A] [dict keys $B]]
}
Note that dict unset
does nothing if the key is absent, which is convenient, and the results are in the order of occurrence of the input keys (strictly in the order of first occurrence, in the case of input lists that are not set-like).
Upvotes: 0
Reputation: 247250
Another approach is to use an array (or a dict):
set list1 {red yellow green blue orange}
set list2 {red green blue orange}
if {[llength $list1] > [llength $list2]} {
set long $list1
set short $list2
} else {
set long $list2
set short $list1
}
foreach elem $long {
set diff($elem) 1
# or: dict set diff $elem 1
}
foreach elem $short {
unset -nocomplain diff($elem)
# or: dict unset diff $elem
}
set difference [array names diff]
# or: set difference [dict keys $diff]
Upvotes: 1
Reputation: 4813
While your code (apart from typos) works, it can be done much simpler like this:
set diff [lmap n [concat $list1 $list2] {
# Skip the elements that are in both lists
if {$n in $list1 && $n in $list2} continue
set n
}]
Upvotes: 2