From: "Benjamin J. Tilly" Date: 2001-06-09T04:27:36+09:00 Subject: [ruby-talk:16341] RE: Tcl string map lookalike >===== Original Message From Wilbert Berendsen ===== >Hi, > >What's the best way to perfomrs a Tcl-like "string map" function. > >Tcl "string map" walks through a string, replacing every occurrence of a >substring with an associated replacement. The substrings and replacement >are in a flat list, and the list is searched from the beginning, so first >matches precede, eg: > >Tcl: > >set str "This is a set map [list "<" "<" "<" ">" "<" "<" ">" ">"] >string map $map $str >===> "This is a " > >Ruby: (????) > >str = "This is a string" >map = ["<", "<", "<", ">", "<", "<", ">", ">"] >str.map (map) >===> "This is a " > >I tried using gsub with an array and a special regexp, but that's a bit >cumbersome. Separate gsub's after eachother don't work, because the >substitutions may again contain matching character which results in >errors. So it must do it in one single pass along the string. > I am working in Perl right now, so I can give a Perl answer which should be fairly easy to translate into Ruby. My apologies for that. The usual Perl hack for this is to construct a hash lookup from string to replacement, and an RE that will only match the keys of your hash. Then do a general substitution, using the hash lookup to get the replacement. The "5 second" Perl version is: sub string_map { my ($str, %lookup) = @_; my $re_str = join "|", map {quotemeta($_)} reverse sort keys %lookup; my $re = qr/($re_str)/; $str =~ s/$re/$lookup{$1}/g; return $str; } This reverses your desired duplication rule. (Last one in wins in building the hash, not the first.) I also have a longest first rule. Normally I figure that if someone has both "foo" and "foobar", they really want to give the "foobar" rule precedence over the "foo" rule. (Hence the reverse sort.) Finally the quotemeta handles escaping pesky characters. The same idea should work perfectly well in Ruby. But you will need to do a lot more work (in either Perl or Ruby) if you want to have TCL's "order-based" precedence of substitutions logic. Cheers, Ben