Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

how to remove list elements at specific indices

2,258 views
Skip to first unread message

iand

unread,
May 17, 2010, 4:24:46 AM5/17/10
to
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

jr4412

unread,
May 17, 2010, 7:19:19 AM5/17/10
to
hi 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 ;)

Larry W. Virden

unread,
May 17, 2010, 7:38:40 AM5/17/10
to
On May 17, 4:24 am, iand <ianda...@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"


Qatanah

unread,
May 17, 2010, 9:30:41 AM5/17/10
to

I think there was a wrapper proc introduce in a book. The proc name
was 'ldelete'..

tom.rmadilo

unread,
May 17, 2010, 2:12:06 PM5/17/10
to

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.

MartinLemburg@Siemens-PLM

unread,
May 18, 2010, 2:53:51 AM5/18/10
to
Hi iand,

sincerely asking for such list elements deletion commands in the core
is always told against, that there is "lreplace" and that, if really,
really needed everybody can do his own lremove, ldelete, etc. proc
based on lreplace. The reason ... the core shouldn't be bloated by
unnecessary crap.

So in my own list commands extension package are some procs caring for
deleting "single" elements or (all) elements matching specified
patterns/contents.
But they all are inefficient or are misusing other functionality.

Example:

# delete an element to be found
set list [lreplace $list [set idx [lsearch $list $element]] $idx];
set list [lsearch -inline -all -not -exact $list $element];

The first line uses temporary tcl variables, the second misuses
lsearch for deletion.

Example:

# delete specified elements
foreach idx [lreverse $idxList] {
set list [lreplace $list $idx $idx];
}

This example code is so normal, so that nobody will argue, but doing
this in core would be a very good optimization. And ... not that long
ago "lreverse" was coded by my own, because it wasn't in the core,
too!
Why everybody has to care for the same reoccurring problem - how to
delete specific elements from a list, without having to build a new
proc.
Why this standard use case is not part of the core?

This discussion is very old, because it can be extended about such
functionality of the set theory - creating unions, intersections,
etc..
There is no build in functionality like "lunion", "lintersect", etc. -
not for lists and not for dicts. There is no maths on list( element)s.

I don't want to extend this discussion too much, but I would be really
glad, if not everybody needs a tcllib or own packages to extend basic
list functionality.

In my eyes adding lreverse was not bloating the core and adding (via a
TIP) lremove or ldelete wouldn't either bloat the core.

Best regards,

Martin
P.S.: sometimes I feel like having to reinvent the wheel using tcl,
just to provide such basic stuff for "internal" data structures. So I
have my own library for lists, strings, ... . But I always found this
a bit annoying, even feeling glad about this possibility to extend tcl
that easily.

iand

unread,
May 18, 2010, 6:11:38 AM5/18/10
to
On May 18, 11:53 am, "MartinLemburg@Siemens-PLM"
> > iand- Hide quoted text -
>
> - Show quoted text -
Thanks for all the solutions.
Since this seems to be a very trivial issue and is needed very often,
It will be really helpful if this feature is atleast added to any
existing "list" command adding an extra option "-removebyindices" with
all the error/exception handling.
like:
cmd $list -removebyindices $indexlist
Since tcl already has powerful list commands in kitty adding few more
trivial features to already existing commands may be really helpful.
Since i am not a programing/scripting guru , I do not know how to
weigh the problems that are associated with adding features like this
to the core. I wish i had this feature and more trivial such features
to an already existing powerful tcl list-operations atleast adding/
extending them with -{options}.

Donal K. Fellows

unread,
May 18, 2010, 6:25:18 AM5/18/10
to
On 18 May, 11:11, iand <ianda...@gmail.com> wrote:
> Since this seems to be a very trivial issue and is needed very often,
> It will be really helpful if this feature is atleast added to any
> existing "list" command adding an extra option "-removebyindices" with
> all the error/exception handling. Like:

>
> cmd $list -removebyindices $indexlist
>
> Since tcl already has powerful list commands in kitty adding few more
> trivial features to already existing commands may be really helpful.
> Since i am not a programing/scripting guru , I do not know how to
> weigh the problems that are associated with adding features like this
> to the core. I wish i had this feature and more trivial such features
> to an already existing powerful tcl list-operations atleast adding/
> extending them with -{options}.

Most of our list manipulation commands don't take any operations; they
do what they do and just do that. There isn't a command to remove
items at indices (perhaps there should be, but there isn't) but as you
can see from this thread, it's pretty easy to add one if only numeric
indices are supported. Supporting non-numeric (i.e., end-relative)
indices would be better done from C, and that might actually be a
reasonable case for us to add an [lremove] command in the future.

Hmm. Ought to TIP that...

Donal.

Donal K. Fellows

unread,
May 18, 2010, 8:09:03 AM5/18/10
to
On 18 May, 11:25, "Donal K. Fellows"

<donal.k.fell...@manchester.ac.uk> wrote:
> Hmm. Ought to TIP that...

Done. See http://tip.tcl.tk/367.html for a more detailed plan. No time
schedule for it yet.

Donal.

Larry W. Virden

unread,
May 18, 2010, 10:52:31 AM5/18/10
to
On May 18, 2:53 am, "MartinLemburg@Siemens-PLM"
<martin.lemburg.siemens-...@gmx.net> wrote:

> P.S.: sometimes I feel like having to reinvent the wheel using tcl,
> just to provide such basic stuff for "internal" data structures. So I
> have my own library for lists, strings, ... . But I always found this
> a bit annoying, even feeling glad about this possibility to extend tcl
> that easily.
>

Note that the tcllib distribution (http://tcllib.sf.net/) is a set of
useful Tcl procs that developers have contributed. Perhaps it would be
worthwhile to add your library to tcllib. That distribution is pretty
common for people to have available in their environment.

tom.rmadilo

unread,
May 18, 2010, 10:59:27 AM5/18/10
to
On May 18, 5:09 am, "Donal K. Fellows"

<donal.k.fell...@manchester.ac.uk> wrote:
> On 18 May, 11:25, "Donal K. Fellows"
>
> <donal.k.fell...@manchester.ac.uk> wrote:
> > Hmm. Ought to TIP that...
>
> Done. See http://tip.tcl.tk/367.htmlfor a more detailed plan. No time
> schedule for it yet.

I guess TIPs are discussed on the Tcl core, but I would just like to
add here that it would be nice to move away from commands which
require using expand syntax {*} and use list syntax for the list of
indices. Note that a list is what is now returned from new commands
like [lsearch -subidices -index ...]. This should also make it much
easier to create byte-code for the command. I propose something
slightly different from my example above:

lremove ?-indexRanges? listVar [list 1 {3 5} 7 9 {11 13} {end-1 end}]

I also propose a helper function, exposed as a command [lranges
listVar rangesList].

It seems to me that users would more often know which list elements or
which ranges of elements they want and creating a new list requires
either a loop to add new elements, or expand, which could be expensive
for large lists as a Tcl proc.


Larry W. Virden

unread,
May 19, 2010, 6:50:11 AM5/19/10
to
On May 17, 4:24 am, iand <ianda...@gmail.com> wrote:
> Is there any command which helps remove the elements of a list with
> specified indices?

Is this an abstract question, or do you have a specific problem that
you are trying to solve? The reason I ask is that with more specific
explanation of the problem you want to solve, a solution for that
problem will be more likely to be able to be offered.

MartinLemburg@Siemens-PLM

unread,
May 19, 2010, 6:50:09 AM5/19/10
to
Hi Larry,

you are right, but I have to ask again my employer, to get his
allowance to publish code I've written some time ago during my work.

Another thing is, that I don't have currently the time to write a
"normal" tcl test suite and to introduce doctools tags for automatic
documentation.
It's not the time for doing it, but the time for learning how to do.

And at last - the sources of my library packages are only tcl 8.5+
compatible. Is this allowed for tcllib packages?

Best regards,

Martin Lemburg

Larry W. Virden

unread,
May 19, 2010, 9:47:04 AM5/19/10
to
On May 19, 6:50 am, "MartinLemburg@Siemens-PLM"
<martin.lemburg.siemens-...@gmx.net> wrote:

> you are right, but I have to ask again my employer, to get his
> allowance to publish code I've written some time ago during my work.

That is certainly understandable and encouraged.

>
> Another thing is, that I don't have currently the time to write a
> "normal" tcl test suite and to introduce doctools tags for automatic
> documentation.
> It's not the time for doing it, but the time for learning how to do.

Perhaps, once you've received an okay to make the code available, you
could try writing up a posting or wiki page describing the library in
enough detail that it might result in recruiting some help for either
writing doc or tests.

>
> And at last - the sources of my library packages are only tcl 8.5+
> compatible. Is this allowed for tcllib packages?
>

That should not be any problem - just make certain the code has the
package require Tcl 8.5 or whatever it requires so that it doesn't try
to load in older tcl environments.

0 new messages