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

后端 未结 9 2025
礼貌的吻别
礼貌的吻别 2020-11-30 01:51

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

I found this site that sh

相关标签:
9条回答
  • 2020-11-30 02:09

    Here is a function that receives text orig dest and replaces in text each character for the one in the corresponding position in 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  = "ÀÂÃÁÉÊÍÓÔÕÜÚÇáàãâêéíóõôúüç";
    var ascii = "AAAAEEIOOOUUCaaaaeeiooouuc";
    console.log(tr("não têm ações em seqüência", port, ascii)) ;
    
    0 讨论(0)
  • 2020-11-30 02:13

    This will map all as to b and all y to 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:

    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('');
    
    0 讨论(0)
  • 2020-11-30 02:16

    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.

    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
    
    0 讨论(0)
  • 2020-11-30 02:17

    In Perl, one can also write

    tr{-_}{+/}
    

    as

    my %trans = (
       '-' => '+',
       '_' => '/',
    );
    
    my $class = join '', map quotemeta, keys(%trans);
    my $re = qr/[$class]/;
    
    s/($re)/$trans{$1}/g;
    

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

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

    0 讨论(0)
  • 2020-11-30 02:25

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

    "aaabbccddeeDDDffd".replace( /(a|cc|DDD|dd)/g, m => ({'a':'B', 'cc':'DDD', 'DDD':'ZZZ', dd:'QQ'}[m]) ) 
    // RESULT: "BBBbbDDDQQeeZZZffd"
    
    0 讨论(0)
  • 2020-11-30 02:28

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

    0 讨论(0)
提交回复
热议问题