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

string map in Tcl

518 views
Skip to first unread message

Glenn Jackman

unread,
Jun 16, 2009, 1:48:00 PM6/16/09
to
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

Jeff Hobbs

unread,
Jun 16, 2009, 1:57:53 PM6/16/09
to
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?
>
>     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

Andreas Leitgeb

unread,
Jun 17, 2009, 8:25:20 AM6/17/09
to
Jeff Hobbs <jeff....@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.

string equal also has -nocase

Glenn Jackman

unread,
Jun 18, 2009, 12:53:04 PM6/18/09
to
At 2009-06-17 08:25AM, "Andreas Leitgeb" wrote:
> >> � � � � � � � � 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 ...].

Good tip, thanks.

0 new messages