lindex, a
built-in Tcl command, retrieves an
element from a
list or a nested list.
See Also edit
- list
- Trees as nested lists
- lindex forward compatibility
- identity function
- one use for lindex
Documentation edit
- official reference
- TIP 22: Multiple Arguments to lindex
- TIP 45: Empty index lists for lindex and lset
Synopsis edit
-
- lindex list ?index ...?
-
- lindex list indexList
Description edit
Returns the
index'th element from
list, where the first element in
list is at index
0. If the index is negative or greater than or equal to the number of elements in list, an empty string is returned. If there is no
index argument,
list is returned even if it is not a well-formed list.
index can be any of the forms described for
string indices.
Where multiple
index arguments are given, they specify a path to an element in a nested list. For example:
lindex {{a b c} {d e f} {g h i}} 1 1 ;# -> e
If one
index' is given, and it is a list of indexes, those indexes also specify a path to a element in a nested list. Thus, these three are equivalent:
lindex $nestedList 1 2 3
lindex $nestedList {1 2 3}
lindex [lindex [lindex $nestedList 1] 2] 3
Without any indices, or with an empty
indexList, the contents of the
list argument are returned without further interpretation, meaning that in this case,
list isn't even checked to make sure it is a properly formatted list. Therefore, any value at all is valid. This can be useful when a function that simply returns its argument is needed.
Discussion edit
LES 2005-08-15: What does
lindex do that
lrange doesn't?
[pmaage
] take less time
schlenk direct access to elements in nested lists.
LES Look, Ma! No lindex!
proc picknested {argList args} {
for {set _depth 0} {$_depth < [llength $args]} {incr _depth} {
set _range [lrange $args $_depth $_depth]
set argList {*}[lrange $argList $_range $_range]
}
return $argList
}
Testing:
% picknested {{a b c} {d e {foo bar hey} f} {g h i}} 0
a b c
% picknested {{a b c} {d e {foo bar hey} f} {g h i}} 0 1
b
% picknested {{a b c} {d e {foo bar hey} f} {g h i}} 1 2
foo bar hey
% picknested {{a b c} {d e {foo bar hey} f} {g h i}} 1 2 0
foo
% picknested {{a b c} {d e {foo bar hey} f} {g h i}} 1 2 2
hey
schlenk: Should have said 'easy' access. You can do the same with
lrange, yes. You do not need all list commands, most can be replaced by a proc (think lsearch, lsort, lreplace, linsert, lindex). Its just a tradeoff how many list commands exist. (see
struct::list for some more). Having more or fewer commands is mostly an optimization in time or space.
Lars H: I'd go further and say
lrange still doesn't give you access to the nested elements--it's really
{*} (and in the case of the indices shimmering) that you rely on to pick out elements of lists (undo whatever list-quoting were applied to them). But why bother with
lrange, when it's all much simpler with
foreach?
proc picknested2 {L args} {
foreach index $args {
if {$index < 0} then {return {}}
foreach L $L {
if {[incr index -1] < 0} then {break}
}
if {$index >= 0} then {return {}}
}
return $L
}
Remove the first and last
if if you don't worry about correct behaviour for out-of-bounds indices.
AMG, perhaps echoing
Lars H:
lrange can't directly be used to obtain a single element from a list. The closest it comes is to return a
list whose sole element is the one you're looking for. The difference is the same as that between a value and a single-element list containing that value. For many values, there is no script-visible difference (unless you're measuring performance, see
shimmering). But you cannot rely on this in general. Here's an example:
lindex {{hello world} {how are you}} 0 ;# hello world
lrange {{hello world} {how are you}} 0 0 ;# {hello world}