For my curiosity, is this a complete way to implement [string map] in plain Tcl?
proc stringmap {maplist s} { if {[llength $maplist] == 0} { return $s } elseif {[llength $maplist] % 2 != 0} { error "char map list unbalanced" } set new "" while {[string length $s] > 0} { set replacement [string index $s 0] set i 1 foreach {key value} $maplist { set len [string length $key] if {$len > 0 && [string match "$key*" $s]} { set replacement $value set i $len break } } append new $replacement set s [string range $s $i end] } return $new }
stringmap {abc 1 ab 2 a 3 1 0} 1abcaababcabababc ;# => 01321221 stringmap {aa X a Y} baaa ;# => bXY stringmap {a Y aa X} baaa ;# => bYYY
-- Glenn Jackman Write a wise saying and your name will live forever. -- Anonymous
> For my curiosity, is this a complete way to implement [string map] in > plain Tcl?
> proc stringmap {maplist s} { > if {[llength $maplist] == 0} { > return $s > } elseif {[llength $maplist] % 2 != 0} { > error "char map list unbalanced" > } > set new "" > while {[string length $s] > 0} { > set replacement [string index $s 0] > set i 1 > foreach {key value} $maplist { > set len [string length $key] > if {$len > 0 && [string match "$key*" $s]} { > set replacement $value > set i $len > break > } > } > append new $replacement > set s [string range $s $i end] > } > return $new > }
> stringmap {abc 1 ab 2 a 3 1 0} 1abcaababcabababc ;# => 01321221 > stringmap {aa X a Y} baaa ;# => bXY > stringmap {a Y aa X} baaa ;# => bYYY
Looks complete, but doesn't support -nocase, which should be possible since string match has a -nocase option. You can try this over the test suite for string map, which should cover all the edge cases.
Jeff Hobbs <jeff.ho...@gmail.com> wrote: > On Jun 16, 10:48 am, Glenn Jackman <gle...@ncf.ca> wrote: >> For my curiosity, is this a complete way to implement [string map] in >> plain Tcl? >> set new "" >> while {[string length $s] > 0} { >> set replacement [string index $s 0] >> set i 1 >> foreach {key value} $maplist { >> set len [string length $key] >> if {$len > 0 && [string match "$key*" $s]} {
To make it really equivalent, you'd have to protect any glob-magic chars in $key, or rather do something like [string equal -length [string length $key] $key $s] instead of the [string match ...].
> Looks complete, but doesn't support -nocase, which should be possible > since string match has a -nocase option.
> To make it really equivalent, you'd have to protect any glob-magic chars > in $key, or rather do something like > [string equal -length [string length $key] $key $s] > instead of the [string match ...].
Good tip, thanks.
-- Glenn Jackman Write a wise saying and your name will live forever. -- Anonymous