Reputation: 61
I have two lists
I am trying to do remove_from_list $a1 $b1 >> {a c d}
Is there a function that can operate on lists on tcl?
Upvotes: 3
Views: 9842
Reputation: 46
# with struct::set from tcllib
package require struct::set
set a1 {a b c d e f}
set b1 {b f e}
struct::set difference $a1 $b1
# result in
d a c
Dokumentation: struct::set
Upvotes: 2
Reputation: 246807
You can also use an array. It's easy to add and remove elements
% foreach elem $a1 {set x($elem) 1}
% foreach elem $b1 {unset x($elem)}
% set result [array names x]
d a c
It's a pretty efficient approach too, only a single pass through each list.
Or use a dictionary to maintain the original insertion order:
% foreach elem $a1 {dict set y $elem 1}
% foreach elem $b1 {dict unset y $elem}
% set result [dict keys $y]
a c d
Upvotes: 3
Reputation: 13252
To begin with, you can't use brackets for list literals. Brackets are used for command substitution in Tcl.
Instead, use the list-making command, list
% set a1 [list a b c d e f]
a b c d e f
Or, more or less equivalently:
% set b1 {b f e}
b f e
There is no standard command to subtract one list from another. It's very easy to construct a filter, though.
You can filter out items in a1
that are in b1
by an lmap
(list map) filter:
lmap item $a1 {
if {$item ni $b1} {
set item
} else {
continue
}
}
# results in
a c d
The if
command inside the lmap
body determines if an item is not in (ni
)$b1
. If this is true, the value of the item becomes a part of the result. If it is false, the item is skipped.
In Tcl 8.5 and earlier, there is no lmap
. In that case, one can copy-and-paste an ersatz lmap
(works the same) into the code: link below.
Or, one can use foreach
instead. It's a little messier but works.
set res {}
foreach item $a1 {
if {$item ni $b1} {
lappend res $item
}
}
% set res
a c d
Documentation: continue, foreach, if, lappend, list, lmap (for Tcl 8.5), lmap, ni (operator), set
Upvotes: 3