27

How te remove an element from TCL list say:

  1. which has index = 4
  2. which has value = "aa"

I have Googled and have not found any built-in function yet.

David Hedlund
  • 128,221
  • 31
  • 203
  • 222
Narek
  • 38,779
  • 79
  • 233
  • 389

7 Answers7

53
set mylist {a b c}
puts $mylist
a b c

Remove by index

set mylist [lreplace $mylist 2 2]
puts $mylist 
a b

Remove by value

set idx [lsearch $mylist "b"]
set mylist [lreplace $mylist $idx $idx]
puts $mylist
a
drysdam
  • 8,341
  • 1
  • 20
  • 23
  • This is great, but my list consists from sublists, and I want to check in each sublist if the value in the second index is 0 (for example), I want to remove that sublist. How I should do that. P.S. The problem is that [lindex $list] returns value not the reference – Narek Apr 18 '11 at 11:27
  • 6
    @Narek Then please update your question to be ask what you want, b/c drysdam answered what you asked. – Trey Jackson Apr 18 '11 at 12:20
  • Please change [lreplace $idx $idx] to [lreplace $mylist $idx $idx]. – Narek May 11 '11 at 05:10
  • 2
    One tiny thing; Shouldn't the result in the last item be `a c`, rather than just `a`? – Andrew Barber Jan 14 '15 at 22:13
17

The other way to remove an element is to filter it out. This Tcl 8.5 technique differs from the lsearch&lreplace method mentioned elsewhere in that it removes all of a given element from the list.

set stripped [lsearch -inline -all -not -exact $inputList $elemToRemove]

What it doesn't do is search through nested lists. That's a consequence of Tcl not putting effort into understanding your data structures too deeply. (You can tell it to search by comparing specific elements of the sublists though, via the -index option.)

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
4

Lets say you want to replace element "b":

% set L {a b c d}
a b c d

You replace the first element 1 and last element 1 by nothing:

% lreplace $L 1 1
a c d
icanhasserver
  • 1,054
  • 10
  • 11
2

regsub may also be suitable to remove a value from a list.

set mylist {a b c}
puts $mylist
  a b c

regsub b $mylist "" mylist

puts $mylist
  a  c
llength $mylist
  2
Shawn E
  • 21
  • 1
1

Just wrapped up what others have done

proc _lremove {listName val {byval false}} {
    upvar $listName list

    if {$byval} {
        set list [lsearch -all -inline -not $list $val]
    } else {
        set list [lreplace $list $val $val]
    }

    return $list
}

Then call with

Inline edit, list lappend
    set output [list 1 2 3 20]
    _lremove output 0
    echo $output
    >> 2 3 20

Set output like lreplace/lsearch
    set output [list 1 2 3 20]
    echo [_lremove output 0]
    >> 2 3 20

Remove by value
    set output [list 1 2 3 20]
    echo [_lremove output 3 true]
    >> 1 2 20

Remove by value with wildcar
    set output [list 1 2 3 20]
    echo [_lremove output "2*" true]
    >> 1 3
Todd Horst
  • 853
  • 10
  • 22
1

You can also try like this :

set i 0
set myl [list a b c d e f]

foreach el $myl {
   if {$el in {a b e f}} {
      set myl [lreplace $myl $i $i]
   } else {
      incr i
   }
}
set myl
0

There are 2 easy ways.

# index
set mylist "a c b"
set mylist [lreplace $mylist 2 2]
puts $mylist 
a b
    
# value
set idx [lsearch $mylist "b"]
set mylist [lreplace $mylist $idx $idx]
puts $mylist
a
esahc
  • 15
  • 4