Wie finden Sie, ob eine bestimmte Zeichenfolge Unicode-Zeichen hat (insb. Double Byte-Zeichen)

StackOverflow https://stackoverflow.com/questions/147824

  •  02-07-2019
  •  | 
  •  

Frage

Um genauer zu sein, muss ich wissen, ob (und wenn möglich, wie) ich, ob eine bestimmte Zeichenfolge Double-Byte-Zeichen finden kann oder nicht hat. Grundsätzlich, ich brauche ein Pop-up öffnen einen bestimmten Text anzuzeigen, die Double-Byte-Zeichen enthalten, wie Chinesisch oder Japanisch. In diesem Fall müssen wir die Fenstergröße anzupassen, als es für Englisch oder ASCII sein würde. Wer hat eine Ahnung?

War es hilfreich?

Lösung

JavaScript hält Text intern als UCS-2, die eine ziemlich umfangreiche Teilmenge von Unicode kodieren kann.

Aber das ist nicht wirklich relevant für Ihre Frage. Eine Lösung könnte sein, eine Schleife durch den String und untersuchen Sie die Zeichencodes an jeder Position:

function isDoubleByte(str) {
    for (var i = 0, n = str.length; i < n; i++) {
        if (str.charCodeAt( i ) > 255) { return true; }
    }
    return false;
}

Dies ist vielleicht nicht so schnell, wie Sie möchten.

Andere Tipps

Ich benutzte mikesamuel Antwort auf diese. Ich bemerkte jedoch vielleicht gerade wegen dieser Form, dass es nur eine Flucht vor dem Schrägstrich u sein sollte, z.B. \u und \\u diese Arbeit nicht richtig zu machen.

function containsNonLatinCodepoints(s) {
    return /[^\u0000-\u00ff]/.test(s);
}

Funktioniert bei mir:)

Ich habe die beiden Funktionen in den oberen Antworten gebenchmarkt und dachte, ich würde die Ergebnisse teilen. Hier ist der Testcode I verwendet:

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

Wenn diese läuft ich habe:

isDoubleByte => 2421
containsNonLatinCodepoints => 868

So für diese bestimmte Zeichenfolge der Regex Lösung ist etwa 3 mal schneller.

Jedoch beachten, dass für eine Zeichenfolge, wo das erste Zeichen Unicode ist, isDoubleByte() kehrt sofort und so viel schneller ist als die regex (die immer noch den Aufwand des regulären Ausdrucks hat).

Zum Beispiel für die Zeichenfolge 中国, ich habe diese Ergebnisse:

isDoubleByte => 51
containsNonLatinCodepoints => 288

Um das Beste aus beiden Welt zu erhalten, ist es wahrscheinlich besser, beide zu kombinieren:

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

In diesem Fall, wenn das erste Zeichen Chinese ist (was wahrscheinlich ist, wenn der gesamte Text Chinese ist), wird die Funktion schnell und sofort zurück. Wenn nicht, wird es die Regex läuft, die noch schneller als einzeln jedes Zeichen zu überprüfen.

Eigentlich sind alle Zeichen Unicode, zumindest aus der Sicht der Javascript-Engine.

Leider wird die bloße Anwesenheit von Zeichen in einem bestimmten Unicode-Bereich nicht ausreicht, um Sie mehr Platz benötigen, um zu bestimmen. Es gibt eine Reihe von Zeichen, die in etwa die gleiche Menge an Speicherplatz als andere Zeichen aufnehmen, die deutlich über dem ASCII-Bereich Unicode-Codepunkte haben. Typografische Anführungszeichen, Zeichen mit diakritischen Zeichen, bestimmte Satzzeichen und verschiedene Währungssymbole sind außerhalb des niedrigen ASCII-Bereich und sind in ganz unterschiedlichen Orten auf der Unicode Basic Multilingual Plane zugeordnet.

Im Allgemeinen Projekte, die ich auf elect gearbeitet habe für alle Sprachen zusätzlichen Platz zu schaffen, oder manchmal Javascript verwenden, um zu bestimmen, ob ein Fenster mit Auto-Scrollbar CSS-Attribut hat eigentlich zufrieden mit einer Höhe, die eine Bildlaufleiste oder nicht auslösen würde.

Wenn das Vorhandensein des Erfassen oder Anzahl von CJK-Zeichen ausreichend sein werden, um Sie ein wenig mehr Platz benötigen zu bestimmen, könnten Sie einen regulären Ausdruck mit den folgenden Bereichen konstruieren: [\ U3300- \ u9fff \ uf900- \ ufaff], und das verwenden, um eine Zählung der Anzahl von Zeichen zu extrahieren, die übereinstimmen. (Dies ist ein wenig zu grobe und vermisst alle Nicht-BMP Fällen schließt wahrscheinlich einige andere relevante Bereiche und die meisten gehören wahrscheinlich einige irrelevant Zeichen, aber es ist ein Ausgangspunkt).

Auch hier sind Sie nur, gehen zu können, eine grobe Heuristik ohne etwas entlang der Linien von einer Volltext Rendering-Engine verwalten, weil, was Sie wirklich wollen, ist so etwas wie GDI MeasureString (oder ein anderes Text-Rendering-Engine-äquivalent). Es ist schon eine Weile her, seit ich so getan habe, aber ich denke, die nächste HTML / DOM äquivalent eine Breite auf einem div setzt und die Anforderung der Höhe (Ausschneiden und Einfügen Wiederverwendung, so entschuldigen, wenn diese Fehler enthält):

o = document.getElementById("test");

document.defaultView.getComputedStyle(o,"").getPropertyValue("height"))

Hier ist Benchmark-Test: http://jsben.ch/NKjKd

Das ist viel schneller:

function containsNonLatinCodepoints(s) {
    return /[^\u0000-\u00ff]/.test(s);
}

als dies:

function isDoubleByte(str) {
    for (var i = 0, n = str.length; i < n; i++) {
        if (str.charCodeAt( i ) > 255) { return true; }
    }
    return false;
}

Warum das Fenster selbst nicht zulassen, die Größe auf der Basis der Laufzeit Höhe / Breite?

Führen Sie so etwas wie dies in Ihrem Pop-up:

window.resizeTo(document.body.clientWidth, document.body.clientHeight);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top