2012-05-23 6 views
29

He estado tratando de descubrir cómo asignar un conjunto de caracteres en una cadena a otro conjunto similar a la función tr en Perl.¿Cómo se asignan los caracteres de reemplazo de mapa en Javascript de forma similar a la función 'tr' en Perl?

Encontré this site that shows equivalent functions in JS and Perl, pero tristemente no hay tr equivalente.

la función tr (transliteración) en Perl mapas de caracteres uno a uno, por lo

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

habría mapa

 - => + and _ =>/

¿Cómo se puede hacer esto de manera eficiente en JavaScript?

Respuesta

39

No hay un built-in equivalente, pero puede acercarse a uno con replace:

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

muy agradable con la función de devolución de llamada, ¿qué devuelve {..} [m] hacer? – qodeninja

+2

@qodeninja El objeto ('{...}') define la asignación de caracteres, con coincidencias esperadas como claves/propiedades y reemplazos como valores. La coincidencia actual, 'm', se usa buscar su propio reemplazo (' [m] ') del objeto, que se devuelve a' reemplazar' para realizar el reemplazo real. –

+0

Aparentemente la respuesta es "sí", pero no tan sucintamente como Perl. –

3

Esto mapear todas a s a b y todos y a 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:

Al parecer, usted no puede hacer eso con cuerdas. He aquí una alternativa:

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

Por qué publicar una respuesta sin probarlo y por qué dejar que la respuesta no laborable en el lugar después de editarlo? –

1

En Perl, también se puede escribir

tr{-_}{+/} 

como

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

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

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

Esta última versión seguramente puede implementarse en JS sin muchos problemas.

(Mi versión carece de la duplicación de solución de Jonathan Lonowski.)

5

no puedo dar fe de 'eficiente' pero esto utiliza una expresión regular y una devolución de llamada para proporcionar el carácter de reemplazo.

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

Para cadenas largas de búsqueda y reemplazo de caracteres, puede valer la pena ponerlos en un hash y hacer que la función vuelva de eso. es decir, tr/abcd/QRST/se convierte en hash {a: Q, b: R, c: S, d: T} y la devolución de llamada devuelve hash [chr].

+1

+1, aunque: no admite "]", "\" y "^". No admite rangos. No admite "\" escapes. – ikegami

4

Método:

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

Un ejemplo perfecto:

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

¿Qué tan eficiente es esto frente a la respuesta? – qodeninja

+1

@qodeninja Es la misma técnica, mientras que este método permite utilizar un mapeo JSON kv dinámico. Puede ser más lento que la respuesta, ya que genera el Regex y el diccionario de reemplazo para usted. Entonces, use este método mientras necesite un reemplazo dinámico, use la respuesta si solo necesita manejar el conjunto de palabras estático. – PeakJi

Cuestiones relacionadas