HE 2015-10-08:
lsearch determines which values in a list match a pattern. I want to determine which patterns in a list match a value.
Here is my solution:
$mode specifies the type of pattern, and is is one of:
$value is a string to apply each pattern to.
$patList is a list of patterns.
searchPatList returns the index of the the first pattern in $patList that matches $value, or -1 if no pattern matches.
proc searchPatList {mode value patList} { set n 0 switch -exact -- $mode { -exact { foreach el $patList { if {$el eq $value} { return $n } incr n } return -1 } -glob { foreach el $patList { if {[string match $el $value]} { return $n } incr n } return -1 } -regexp { foreach el $patList { if {[regexp -- $el $value]} { return $n } incr n } return -1 } default { error "Unknown mode '$mode'!" } } return }
And the examples:
set patList [list \ {test 3.4.1} \ {dummy} \ {^test *[0-9.]*$} \ {test *} \ ] searchPatList -exact {test 3.4.1} $patList 0 searchPatList -exact {test 3.4.2} $patList -1 searchPatList -exact {dummy} $patList 1 searchPatList -glob {test 3.4.1} $patList 0 searchPatList -glob {test 3.4.2} $patList 3 searchPatList -glob {dummy} $patList 1 searchPatList -regexp {test 3.4.1} $patList 0 searchPatList -regexp {test 3.4.2} $patList 2 searchPatList -regexp {dummy} $patList 1 searchPatList -default {dummy} $patList Unknown mode '-default'!
PYK 2015-10-08:
$patList mixes patterns which are clearly intended to be used with some particular command, yet searchPatList only operates in one mode at a time, making the overall design a bit over-engineered. This type of situation just might be the right place to use if without bracing the expressions:
set matchers { {{test 3.4.1} eq [lindex @val@]} {0 && [lindex @val@]} {[string match {^test *[0-9.]*$} @val@]} {[string match {test *} @val@]} } foreach matcher $matchers { if [string map [list @val@ [list $val]] $matcher] { puts [list matched $matcher] break } }
The advantages of this approach are that patterns and their associated commands appear together, and arbitrary matching algorithms can be introduced as needed. The [lindex @val@] bit serves merely as an identity function, which is one way to properly quote a value being inserted into an expr template. Note also that list $val is the right way to quote a value being inserted into a Tcl script.