Sé que el encabezado de estas preguntas parece vago, pero es porque simplemente no sé cómo resumirlo adecuadamente.

Estoy trabajando en un proyecto donde ingreso un texto y se traduce en otra cosa.

Hay un violín aquí.

Si ingreso 4 , se traduce a la palabra para .

Si ingreso b4 , debería traducirse a antes .

En cambio, se traduce a bfor , porque captura la variable 4 como una variable separada.

Intenté cambiar el orden, pero no funciona. ¿Es este un problema de expresiones regulares?

Mis variables se identifican en el JS.

var replaceValues = {
    '4' : 'for',
    'b4' : 'before'
}

$('.bs-text').keyup(function (event) {
    newText = event.target.value;
    for (var txt in replaceValues) {
        var temp = new RegExp(txt, 'gim');
        newText = newText.replace(temp, replaceValues[txt]);
    }
    $('.human-text').text(newText);
});
2
webfrogs 27 oct. 2017 a las 20:05

3 respuestas

La mejor respuesta

Como señalé en los comentarios, los objetos JS no tienen un orden definido de sus teclas, por lo que no es una buena idea contar con esto cuando se sabe que el diccionario se hará mucho más grande.

Más información sobre esto en otra pregunta SO: ¿JavaScript garantiza el orden de la propiedad del objeto?

En su lugar, use una matriz simple que tendrá el orden que defina. La clasificación de esta matriz de diccionario también se puede hacer en JS, no es necesario que maneje esto usted mismo.

var replaceValues = [
  {key: '4', value: 'for'},
  {key: 'b4', value: 'before'},
];

// sort the values so longer keys go first
replaceValues.sort((a, b) => b.key.length - a.key.length);

$('.bs-text').keyup(function (event) {
    var newText = event.target.value;
    for (var txt in replaceValues) {
        var replacement = replaceValues[txt];
        var temp = new RegExp(replacement.key, 'gim');
        newText = newText.replace(temp, replacement.value);
    }
    $('.human-text').text(newText);
});

También puede usar ES6 Map, debería tener el pedido garantizado. Pero tenga en cuenta que no es suficiente crear Map desde Object:

Un objeto Map itera sus elementos en orden de inserción: un for ... of loop devuelve una matriz de [clave, valor] para cada iteración.

Cabe señalar que un Mapa que es un mapa de un objeto, especialmente un diccionario de diccionarios, solo se asignará al orden de inserción del objeto, que es aleatorio y no está ordenado.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Objects_and_maps_compared

1
Martin Adámek 27 oct. 2017 a las 18:43

Como se menciona en los comentarios, primero debe buscar la coincidencia más larga . Una opción es generar una expresión regular única a partir de las palabras de búsqueda, ordenadas por longitud, y use una devolución de llamada para obtener el valor de reemplazo correcto.

var replaceValues = {
  '4': 'for',
  'b4': 'before'
};

// generates something equivalent to `/b4|4/gmi`
var pattern = new RegExp(
  Object.keys(replaceValues)
  .sort((a, b) => b.length - a.length)
  .join('|'),
  'gmi'
);

var newText = '4 me b4 me';
console.log(newText.replace(pattern, match => replaceValues[match]));

Esto funciona porque el motor regex coincide con las alternativas de izquierda a derecha (es decir, si b4 coincide, no intentará coincidir con 4). No estoy seguro de cómo esta solución se escala con más palabras de búsqueda, pero en realidad podría ser mejor porque solo está haciendo coincidir la cadena una vez en lugar de n veces, es decir, el motor de expresiones regulares no tiene que atravesar el cadena completa varias veces.

1
Felix Kling 27 oct. 2017 a las 17:34

La propiedad del objeto tiene un carácter ":" dentro del valor de la propiedad

$('.bs-text').keyup(function (event) {
    var newText = event.target.value;
    if (replaceValues[newText]) {
      $('.human-text').text(replaceValues[newText])
    };        
});

Jsfiddle http://jsfiddle.net/je89deam/5/

0
guest271314 27 oct. 2017 a las 17:14