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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10726638/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 10:49:54  来源:igfitidea点击:

How do you map-replace characters in Javascript similar to the 'tr' function in Perl?

javascriptperlcharacter-encodingtransliteration

提问by qodeninja

I've been trying to figure out how to map a set of characters in a string to another set similar to the trfunction in Perl.

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

I found this site that shows equivalent functions in JS and Perl, but sadly no tr equivalent.

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

the tr(transliteration) function in Perl maps characters one to one, so

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

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

would map

会映射

     - => + and _ => /

How can this be done efficiently in JavaScript?

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

回答by Jonathan Lonowski

There isn't a built-in equivalent, but you can get close to one with replace:

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

data = data.replace(/[\-_]/g, function (m) {
    return {
        '-': '+',
        '_': '/'
    }[m];
});

回答by neniu

I can't vouch for 'efficient' but this uses a regex and a callback to provide the replacement character.

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

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;
}

For long strings of search and replacement characters, it might be worth putting them in a hash and have the function return from that. ie, tr/abcd/QRST/ becomes the hash { a: Q, b: R, c: S, d: T } and the callback returns hash[ chr ].

对于长字符串的搜索和替换字符,可能值得将它们放入散列中并让函数从中返回。即,tr/abcd/QRST/ 成为散列 { a: Q, b: R, c: S, d: T } 并且回调返回 hash[ chr ]。

回答by PeakJi

Method:

方法:

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];
    });
};

A perfect example:

一个完美的例子:

var s = "I think Peak rocks!"
s.mapReplace({"I think":"Actually","rocks":"sucks"})
// console: "Actually Peak sucks!"

回答by Данила Летуновский

This functions, which are similar how it's built in Perl.

这个函数,类似于它在 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($_);

回答by qwertymk

This will map all as to band all yto z

这会将所有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];

EDIT:

编辑:

Apparently you can't do that with strings. Here's an alternative:

显然你不能用字符串来做到这一点。这是一个替代方案:

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('');

回答by ikegami

In Perl, one can also write

在 Perl 中,也可以写

tr{-_}{+/}

as

作为

my %trans = (
   '-' => '+',
   '_' => '/',
);

my $class = join '', map quotemeta, keys(%trans);
my $re = qr/[$class]/;

s/($re)/$trans{}/g;

This latter version can surely be implemented in JS without much trouble.

后一个版本肯定可以在 JS 中轻松实现。

(My version lacks the duplication of Jonathan Lonowski's solution.)

(我的版本缺少 Jonathan Lonowski 解决方案的重复。)

回答by randomraccoon

I wanted a function that allows passing a custom map object, so I wrote one based on Jonathan Lonowski's answer. If you are trying to replace special characters (the kind that need to be escaped in regular expressions) you'll have to do some more work.

我想要一个允许传递自定义地图对象的函数,所以我根据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]);
};

And it's used like this:

它是这样使用的:

const map = { a: 'A', b: 'B', d: 'D' };
mapReplace('abcde_edcba', map);
// ABcDe_eDcBA

回答by ndvo

Here is a function that receives text orig dest and replaces in text each character for the one in the corresponding position in dest.

这是一个接收文本 orig dest 并将文本中的每个字符替换为 dest 中相应位置的函数的函数。

Is is not good enough for cases where more than one character must be replaced by only one or vice-versa. It is not good enough for removing accents from Portuguese texts, which is my use case.

对于多个字符必须仅替换为一个或反之亦然的情况,这是不够好。从葡萄牙语文本中删除重音还不够好,这是我的用例。

function tr(text, orig, dest) {
    console.assert(orig.length == dest.length);
    const a = orig.split('').map(i=> new RegExp(i, 'g'));
    const b = dest.split('');
    return a.reduce((prev, curr, idx) => prev.replace(a[idx], b[idx]), text );
}

How to use it:

如何使用它:

var port  = "à??áéêíó??üú?áà?aêéíó??úü?";
var ascii = "AAAAEEIOOOUUCaaaaeeiooouuc";
console.log(tr("n?o têm a??es em seqüência", port, ascii)) ;

回答by Vladislav Savchuk

Similiar to Jonathan Lonowski answer but with words support, not just single tr chars

类似于 Jonathan Lonowski 的回答,但有文字支持,而不仅仅是单个 tr 字符

"aaabbccddeeDDDffd".replace( /(a|cc|DDD|dd)/g, m => ({'a':'B', 'cc':'DDD', 'DDD':'ZZZ', dd:'QQ'}[m]) ) 
// RESULT: "BBBbbDDDQQeeZZZffd"