palabras - obtener los dos ultimos caracteres de una cadena javascript
Cómo encontrar si una cadena en particular tiene caracteres Unicode(especialmente caracteres de doble byte) (5)
¿Por qué no dejar que la ventana se redimensione en función de la altura / ancho de ejecución?
Ejecute algo como esto en su ventana emergente:
window.resizeTo(document.body.clientWidth, document.body.clientHeight);
Para ser más precisos, necesito saber si (y si es posible, cómo) puedo encontrar si una cadena dada tiene caracteres de doble byte o no. Básicamente, necesito abrir una ventana emergente para mostrar un texto dado que puede contener caracteres de doble byte, como chino o japonés. En este caso, debemos ajustar el tamaño de la ventana de lo que sería para inglés o ASCII. Alguien tiene una pista?
De hecho, todos los personajes son Unicode, al menos desde la perspectiva del motor Javascript.
Desafortunadamente, la mera presencia de personajes en un rango Unicode particular no será suficiente para determinar que necesitas más espacio. Hay una serie de caracteres que ocupan aproximadamente la misma cantidad de espacio que otros caracteres que tienen puntos de código Unicode muy por encima del rango ASCII. Las comillas tipográficas, los caracteres con signos diacríticos, ciertos signos de puntuación y varios símbolos de moneda están fuera del rango ASCII bajo y se asignan en lugares bastante dispares en el plano multilingüe básico de Unicode.
En general, los proyectos en los que he trabajado eligen proporcionar espacio adicional para todos los idiomas, o algunas veces usan javascript para determinar si una ventana con atributos auto-scrollbar css realmente tiene contenido con una altura que activaría o no una barra de desplazamiento.
Si la detección de la presencia o el recuento de caracteres CJK será adecuada para determinar si necesita un poco de espacio adicional, podría construir una expresión regular usando los siguientes rangos: [/ u3300- / u9ffff u900- / ufaff], y usar que para extraer un recuento de la cantidad de caracteres que coinciden. (Esto es un poco excesivamente grosero, y omite todos los casos que no son BMP, probablemente excluye algunos otros rangos relevantes, y muy probablemente incluye algunos caracteres irrelevantes, pero es un punto de partida).
Nuevamente, solo podrá administrar una heurística aproximada sin algo parecido a un motor de renderizado de texto completo, porque lo que realmente quiere es algo como MeasureString de GDI (o cualquier otro motor de representación de texto equivalente). Ha pasado un tiempo desde que lo hice, pero creo que el equivalente HTML / DOM más cercano es establecer un ancho en un div y solicitar la altura (cortar y pegar la reutilización, así que le pido disculpas si contiene errores):
o = document.getElementById("test");
document.defaultView.getComputedStyle(o,"").getPropertyValue("height"))
Usé la respuesta de mikesamuel en este caso. Sin embargo, me di cuenta quizás debido a esta forma que solo debería haber una barra de escape antes de la u
, por ejemplo, y no para hacer que esto funcione correctamente.
function containsNonLatinCodepoints(s) {
return /[^/u0000-/u00ff]/.test(s);
}
Funciona para mi :)
JavaScript contiene texto internamente como UCS-2, que puede codificar un subconjunto bastante extenso de Unicode.
Pero eso no es realmente relacionado con tu pregunta. Una solución podría ser recorrer la cadena y examinar los códigos de los caracteres en cada posición:
function isDoubleByte(str) {
for (var i = 0, n = str.length; i < n; i++) {
if (str.charCodeAt( i ) > 255) { return true; }
}
return false;
}
Esto podría no ser tan rápido como te gustaría.
Hice una evaluación comparativa de las dos funciones en las respuestas principales y pensé que compartiría los resultados. Aquí está el código de prueba que utilicé:
const text1 = `The Chinese Wikipedia was established along with 12 other Wikipedias in May 2001. 中文維基百科的副標題是「海納百川,有容乃大」,這是中国的清朝政治家林则徐(1785年-1850年)於1839年為`;
const regex = /[^/u0000-/u00ff]/; // Small performance gain from pre-compiling the regex
function containsNonLatinCodepoints(s) {
return regex.test(s);
}
function isDoubleByte(str) {
for (var i = 0, n = str.length; i < n; i++) {
if (str.charCodeAt( i ) > 255) { return true; }
}
return false;
}
function benchmark(fn, str) {
let startTime = new Date();
for (let i = 0; i < 10000000; i++) {
fn(str);
}
let endTime = new Date();
return endTime.getTime() - startTime.getTime();
}
console.info(''isDoubleByte => '' + benchmark(isDoubleByte, text1));
console.info(''containsNonLatinCodepoints => '' + benchmark(containsNonLatinCodepoints, text1));
Al ejecutar esto obtuve:
isDoubleByte => 2421
containsNonLatinCodepoints => 868
Entonces, para esta cadena en particular, la solución de expresiones regulares es aproximadamente 3 veces más rápida.
Sin embargo, tenga en cuenta que para una cadena en la que el primer carácter es unicode, isDoubleByte()
vuelve inmediatamente y, por lo tanto, es mucho más rápido que la expresión regular (que todavía tiene la sobrecarga de la expresión regular).
Por ejemplo, para la cadena 中国
, obtuve estos resultados:
isDoubleByte => 51
containsNonLatinCodepoints => 288
Para obtener lo mejor de ambos, probablemente sea mejor combinar ambos:
var regex = /[^/u0000-/u00ff]/; // Small performance gain from pre-compiling the regex
function containsDoubleByte(str) {
if (!str.length) return false;
if (str.charCodeAt(0) > 255) return true;
return regex.test(str);
}
En ese caso, si el primer carácter es chino (que es probable si todo el texto es chino), la función será rápida y regresará de inmediato. Si no, ejecutará la expresión regular, que es aún más rápido que comprobar cada carácter individualmente.