From: iand on
Is there any command which helps remove the elements of a list with
specified indices?
lrem $list -indices {$indexlist}
or
lrem $list -indices {0 3 5 8} which reconstructs the list removing the
elements at indices mentioned.
lreplace, lindex works with the ranges but not helpful with discrete
indices.

Please help.

Cheers,
iand
From: jr4412 on
hi iand,

On May 17, 9:24 am, iand <ianda...(a)gmail.com> wrote:
> Is there any command which helps remove the elements of a list with
> specified indices?
> lrem $list -indices {$indexlist}
> or
> lrem $list -indices {0 3 5 8} which reconstructs the list removing the
> elements at indices mentioned.
> lreplace, lindex works with the ranges but not helpful with discrete
> indices.
>
> Please help.
>
> Cheers,
> iand

yes, there will be a 'lrem' command as soon as you write the procedure
which wraps the required lreplace etc command(s) -- that's what
extensibility is all about ;)
From: Larry W. Virden on
On May 17, 4:24 am, iand <ianda...(a)gmail.com> wrote:
> Is there any command which helps remove the elements of a list with
> specified indices?

The idea you are asking about is the ability to say "delete members 1
3 5 and 7 of list xyz"?

I don't know of a specific variety of lreplace to do that. However,
it seems to me that something like this pseudo code would be possible


proc lrem { inList args } {
if { ! [string equal [lindex $args 0] "-indices"]} {
puts stderr "USAGE: $::argv0 list -indices {indexlist}"
return {}
}

set indices [lrange $args 1 end]
puts "indices = $indices"
set sortedindices [ lsort -integer -decreasing {*}$indices]
puts "sortedindices = $sortedindices"
foreach i $sortedindices {
puts "i = $i"
set inList [lreplace $inList $i $i]
puts "inList = $inList"
}
puts "returning inList = $inList"
return $inList
}

set l [list 1 a 2 b 3 c 4 d]
set rc [lrem $l -indices [list 2 4 6]]
puts "rc = $rc"


From: Qatanah on
On May 17, 4:24 pm, iand <ianda...(a)gmail.com> wrote:
> Is there any command which helps remove the elements of a list with
> specified indices?
> lrem $list -indices {$indexlist}
> or
> lrem $list -indices {0 3 5 8} which reconstructs the list removing the
> elements at indices mentioned.
> lreplace, lindex works with the ranges but not helpful with discrete
> indices.
>
> Please help.
>
> Cheers,
> iand

I think there was a wrapper proc introduce in a book. The proc name
was 'ldelete'..
From: tom.rmadilo on
On May 17, 1:24 am, iand <ianda...(a)gmail.com> wrote:
> Is there any command which helps remove the elements of a list with
> specified indices?
> lrem $list -indices {$indexlist}
> or
> lrem $list -indices {0 3 5 8} which reconstructs the list removing the
> elements at indices mentioned.
> lreplace, lindex works with the ranges but not helpful with discrete
> indices.

Here is a version which takes care of a number of potential problems:

# Note: lranges returns potentially overlapping ranges
proc ::lranges { listVar {lRanges {{0 end}}} } {

upvar $listVar inList

set outList [list]

foreach range $lRanges {
lappend outList {*}[lrange $inList {*}$range]
}
return $outList
}

# lremove removes ranges from list by
# first inverting the list, then using lranges.
# Ugly, but seems to work:

proc ::lremove { listVar {lRanges {{0 end}}} } {

upvar $listVar inList

set endIndex [expr {[llength $inList] - 1}]
set rBegin 0
set rEnd $endIndex

set outRanges [list]

puts "lRanges = $lRanges"

foreach range [lsort -integer -index 0\
[lsort -integer -index 1 -decreasing\
[string map [list end $endIndex] $lRanges]]] {

set rangeBegin [expr [lindex $range 0]]
set rangeEnd [expr [lindex $range 1]]

puts "range = '$range', rBegin = $rBegin, rEnd = $rEnd, rangeBegin =
$rangeBegin rangeEnd = $rangeEnd"
if {$rangeBegin == $rBegin} {
set rBegin [expr $rangeEnd+1]
lappend begin $rBegin
lappend end $rEnd
continue
}
if {$rangeEnd == $rEnd} {
set rEnd [expr $rangeBegin-1]
lappend begin $rBegin
lappend end $rEnd
continue
}

lappend begin $rBegin
lappend end [expr $rangeBegin -1]
lappend begin [expr $rangeEnd+1]
lappend end $rEnd

}

set begin [lsort -integer -unique $begin]
set end [lsort -integer -unique $end]

puts "begin = $begin, end = $end"
puts "rBegin = $rBegin, rEnd = $rEnd"
set i 0
foreach beg $begin {
if {$beg < $rBegin} {
set beg $rBegin
}
set en [lindex $end $i]
if {$en eq ""} {
break
} elseif {$en > $rEnd} {
set en $rEnd
}

lappend outRanges [list $beg $en]
incr i
}
puts "outRanges = [lsort -unique $outRanges]"
#return [lsort -unique $outRanges]
return [lranges inList [lsort -unique $outRanges]]
}

# Example:
set list [list a b c d e f g h i j]
lremove list [list {0 5}]

lremove list [list {0 2}]

lremove list [list {0 2} {3 5}]

puts "[lremove list {{3 5} {0 2} {8 9}}]"

# should return "g h" as a two element list.

Note that [lremove] works with "end", but not with "end-1", etc.