您如何映射替换 Javascript 中的字符,类似于 Perl 中的“tr”函数?

IT技术 javascript perl character-encoding transliteration
2021-03-12 14:26:12

我一直在试图弄清楚如何将字符串中的一组字符映射到类似于trPerl 中函数的另一组字符

我发现这个站点显示了 JS 和 Perl 中的等效功能,但遗憾的是没有 tr 等效功能。

trPerl 中(音译)函数将字符一一映射,所以

     data =~ tr|\-_|+/|;

会映射

     - => + and _ => /

如何在 JavaScript 中有效地做到这一点?

6个回答

没有内置的等效项,但您可以通过以下方式接近一个replace

data = data.replace(/[\-_]/g, function (m) {
    return {
        '-': '+',
        '_': '/'
    }[m];
});
不确定它的性能,但将对象(“字典”)定义为全局变量可能会更快(避免每次重新创建)。
2021-04-21 14:26:12
当我们有一个arr充满此类替换的数组,并且匹配遵循可以完全由正则表达式给出的简单模式时,如果正则表达式有点通用并且匹配了不在arr. 在这种情况下,函数体应该return arr[m] || m;只返回匹配本身而不进行任何替换(而不是undefined)。
2021-05-09 14:26:12
@qdeninja 对象 ( {...}) 定义了字符映射,预期匹配作为键/属性和替换作为值。m然后使用当前匹配,[m]从对象中查找它自己的替换(),返回replace到执行实际替换。
2021-05-11 14:26:12
显然答案是肯定的,但不如 Perl 简洁。
2021-05-13 14:26:12
回调函数非常好, return{..}[m] 有什么作用?
2021-05-14 14:26:12

方法:

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!"
@qdeninja 这是相同的技术,而此方法允许使用动态 JSON kv 映射。它可能比答案慢,因为它会为您生成 Regex 和替换字典。所以当你需要动态替换时使用这种方法,如果你只需要处理静态字集,请使用答案。
2021-05-07 14:26:12

我不能保证“高效”,但这使用正则表达式和回调来提供替换字符。

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 ]。

@ikegami 在这里看到我试图加强这个功能的尝试:codereview.stackexchange.com/questions/192385/...
2021-04-25 14:26:12
+1,即使:不支持“]”、“\”和“^”。不支持范围。不支持“\”转义。
2021-04-26 14:26:12

这个函数,类似于它在 Perl 中的构建方式。

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)
2021-05-16 14:26:12

这会将所有as映射b和所有yz

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('');
为什么在没有测试的情况下发布答案,为什么在编辑后保留不起作用的答案?
2021-04-18 14:26:12