Version 2 of Recursive list searching

Updated 2002-07-17 12:56:03

Richard Suchenwirth 2002-07-17 - Since Tcl 8.4, lindex and the new lset command take multiple indices to retrieve or modify an element in a nested list. To complement these two new goodies, here's a recursive lsearch that returns an index list, of the first occurrence of the wanted item, as can be used by lindex or lset, or -1 if the element was not found.

Note that the search goes down as long as an element can be interpreted as a list of more than one element, so intended strings like "John F Kennedy" will also be searched, e.g. for F. Note also that the result often is a list, so comparisons should be limited to == -1 or != -1.

 proc lrsearch {list el {prefix {}} } {
    set pos [lsearch $list $el]
    if {$pos != -1} {return [concat $prefix $pos]}
    for {set i 0} {$i<[llength $list]} {incr i} {
        set ilist [lindex $list $i]
        if {[llength $ilist]>1} {
            set pos [lrsearch $ilist $el [concat $prefix $i]]
            if {$pos != -1} {return $pos}
        }
    }
    return -1
 }

 % lrsearch {a b {c {d e}}} a
 0
 % lrsearch {a b {c {d e}}} b
 1
 % lrsearch {a b {c {d e}}} c
 2 0
 % lrsearch {a b {c {d e}}} d
 2 1 0
 % lrsearch {a b {c {d e}}} e
 2 1 1
 % lrsearch {a b {c {d e}}} f
 -1

However, nested lists with just one element escape attention:^(

 % lrsearch {a {{b c}} d} b
 -1
 % lrsearch {a {b c} d} b
 1 0

Additional list functions | Arts and crafts of Tcl-Tk programming