我一直在尝试找出如何将字符串中一组字符映射到另一组类似于Perl中tr
函数的设置。
我发现了这个网站,它展示了JS和Perl中等效的函数,但可惜没有类似的tr函数。
Perl中的tr
(转换)函数一对一地映射字符,因此
data =~ tr|\-_|+/|;
would map - => + and _ => /
如何在JavaScript中高效地完成此操作?
我一直在尝试找出如何将字符串中一组字符映射到另一组类似于Perl中tr
函数的设置。
我发现了这个网站,它展示了JS和Perl中等效的函数,但可惜没有类似的tr函数。
Perl中的tr
(转换)函数一对一地映射字符,因此
data =~ tr|\-_|+/|;
would map - => + and _ => /
如何在JavaScript中高效地完成此操作?
没有内置的等价物,但您可以使用replace
方法来实现相似的功能:
data = data.replace(/[\-_]/g, function (m) {
return {
'-': '+',
'_': '/'
}[m];
});
{...}
)定义了字符映射,期望匹配作为键/属性,替换内容作为值。当前匹配项 m
被用作查找对象中对应的替换项([m]
),并将其返回给 replace
函数以执行实际的替换。 - Jonathan Lonowskiarr
,并且匹配遵循可以完全由正则表达式给出的简单模式时,如果正则表达式有点太普遍并且匹配了不在arr
中的内容,则最好有一个默认值。 在这种情况下,函数体应该是return arr[m] || m;
,以返回匹配本身而没有任何替换(而不是undefined
)。 - Mike方法:
String.prototype.mapReplace = function(map) {
var regex = [];
for(var key in map)
regex.push(key.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"));
return this.replace(new RegExp(regex.join('|'),"g"),function(word){
return map[word];
});
};
var s = "I think Peak rocks!"
s.mapReplace({"I think":"Actually","rocks":"sucks"})
// console: "Actually Peak sucks!"
我不能保证“高效”,但这个方法使用正则表达式和回调来提供替换字符。
function tr( text, search, replace ) {
// Make the search string a regex.
var regex = RegExp( '[' + search + ']', 'g' );
var t = text.replace( regex,
function( chr ) {
// Get the position of the found character in the search string.
var ind = search.indexOf( chr );
// Get the corresponding character from the replace string.
var r = replace.charAt( ind );
return r;
} );
return t;
}
对于长字符串的搜索和替换字符,将它们放入哈希表中并让函数从中返回可能是值得的。例如,tr/abcd/QRST/ 变成了哈希表 { a: Q, b: R, c: S, d: T },回调返回 hash[chr]。
function s(a, b){ $_ = $_.replace(a, b); }
function tr(a, b){ [...a].map((c, i) => s(new RegExp(c, "g"), b[i])); }
$_ = "Εμπεδοκλης ο Ακραγαντινος";
tr("ΑΒΓΔΕΖΗΘΙΚΛΜΝΟΠΡΣΤΥΦΧΩ", "ABGDEZITIKLMNOPRSTIFHO");
tr("αβγδεζηθικλμνοπρστυφχω", "abgdezitiklmnoprstifho");
s(/Ξ/g, "X"); s(/Ψ/g, "Ps");
s(/ξ/g, "x"); s(/ψ/g, "Ps");
s(/ς/g, "s");
console.log($_);
s()
是什么以及如何使用tr()
。理想情况下只需要一个函数tr(x,from,to)
。 - Peter Krauss另一种解决方案:
var data = data.replace(/[-_]/g, (match) => {
return '+/'['-_'.indexOf(match)];
});
在Replace的第二个参数中,一个函数将会被调用来替换第一个参数中正则表达式的每一个匹配项,并且它的返回值将作为替换文本。
我希望有一个函数可以传递自定义的地图对象,所以我根据Jonathan Lonowski的答案编写了一个。如果你想替换特殊字符(那些需要在正则表达式中转义的字符),你需要做更多的工作。
const mapReplace = (str, map) => {
const matchStr = Object.keys(map).join('|');
if (!matchStr) return str;
const regexp = new RegExp(matchStr, 'g');
return str.replace(regexp, match => map[match]);
};
const map = { a: 'A', b: 'B', d: 'D' };
mapReplace('abcde_edcba', map);
// ABcDe_eDcBA
这将把所有的a
映射到b
,并把所有的y
映射到z
var map = { a: 'b', y: 'z' };
var str = 'ayayay';
for (var i = 0; i < str.length; i++)
str[i] = map[str[i]] || str[i];
编辑:
显然你不能用字符串做到那个。这里有一个替代方案:
var map = { a: 'b', y: 'z' };
var str = 'ayayay', str2 = [];
for (var i = 0; i < str.length; i++)
str2.push( map[str[i]] || str[i] );
str2.join('');
tr{-_}{+/}
作为
my %trans = (
'-' => '+',
'_' => '/',
);
my $class = join '', map quotemeta, keys(%trans);
my $re = qr/[$class]/;
s/($re)/$trans{$1}/g;
这个版本可以很容易地在JS中实现。
(我的版本缺少Jonathan Lonowski解决方案的复制。)
类似于Jonathan Lonowski的答案,但支持单个字符以外的词语
"aaabbccddeeDDDffd".replace( /(a|cc|DDD|dd)/g, m => ({'a':'B', 'cc':'DDD', 'DDD':'ZZZ', dd:'QQ'}[m]) )
// RESULT: "BBBbbDDDQQeeZZZffd"
只用一个映射表:
const map = {
'-': '+',
'_': '/'
};
data = Object.entries(map).reduce((prev, entry) => prev.replace(...entry), data);