Подтвердить что ты не робот

Как вы заменяете символы в Javascript, аналогичные функции "tr" в Perl?

Я пытался выяснить, как сопоставить набор символов в строке с другим набором, аналогичным функции tr в Perl.

Я нашел этот сайт, который показывает эквивалентные функции в JS и Perl, но, к сожалению, нет tr-эквивалента.

Функция tr (транслитерация) в Perl отображает символы один в один, поэтому

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

будет отображать

     - => + and _ => /

Как это можно сделать эффективно в JavaScript?

4b9b3361

Ответ 1

Нет встроенного эквивалента, но вы можете приблизиться к replace:

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

Ответ 2

Я не могу ручаться за "эффективный", но в нем используется регулярное выражение и обратный вызов для обеспечения замены символа.

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

Ответ 3

Метод:

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!"

Ответ 4

Это отобразит все 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];

EDIT:

По-видимому, вы не можете сделать это со строками. Вот альтернатива:

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

Ответ 5

Эти функции аналогичны тем, как они встроены в 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($_);

Ответ 6

В Perl можно также написать

tr{-_}{+/}

а

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

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

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

Эта последняя версия, несомненно, может быть реализована в JS без особых проблем.

(В моей версии отсутствует дублирование решения Джонатана Лоновски.)

Ответ 7

Я хотел функцию, позволяющую передавать пользовательский объект карты, поэтому я написал ее на основе ответа Джонатана Лоновски. Если вы пытаетесь заменить специальные символы (такие, которые должны быть экранированы в регулярных выражениях), вам придется проделать дополнительную работу.

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