Eingang:
Hello world👩🦰👩👩👦👦
Gewünschte Ausgabe:
👩👩👦👦👩🦰dlrow olleH
Ich habe verschiedene Ansätze ausprobiert, aber keiner hat mir die richtige Antwort gegeben.
Dies schlug kläglich fehl:
const text = 'Hello world👩🦰👩👩👦👦';
const reversed = text.split('').reverse().join('');
console.log(reversed);
Das funktioniert irgendwie, aber es zerfällt 👩👩👦👦
in 4 verschiedene Emojis:
const text = 'Hello world👩🦰👩👩👦👦';
const reversed = [...text].reverse().join('');
console.log(reversed);
Ich habe auch jede Antwort in dieser Frage ausprobiert , aber keine davon funktioniert.
Gibt es eine Möglichkeit, die gewünschte Ausgabe zu erhalten?
javascript
string
emoji
Hao Wu
quelle
quelle
�
Charaktere dargestellt wird, und dann gibt es ein zusätzliches Verbindungszeichen, den Charcode 8205, und dann gibt es zwei weitere , die "rotes Haar" darstellen, und diese 5 Zeichen zusammen meine "Frauengesicht mit roten Haaren"Antworten:
Wenn Sie dazu in der Lage sind, verwenden Sie die
_.split()
von lodash bereitgestellte Funktion . Ab Version 4.0 ab,_.split()
ist die Aufspaltung Unicode Emojis fähig.Die Verwendung des Native
.reverse().join('')
zum Umkehren der 'Zeichen' sollte mit Emojis mit Joinern mit der Breite Null problemlos funktionierenfunction reverse(txt) { return _.split(txt, '').reverse().join(''); } const text = 'Hello world👩🦰👩👩👦👦'; console.log(reverse(text));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>
quelle
reverse("뎌쉐")
festgestellt wurde , dass dies fehlschlägt (2 koreanische Grapheme), was "ᅰ셔 ᄃ" (3 Grapheme) ergibt.Ich nahm die Idee von TKoL, das
\u200d
Zeichen zu verwenden, und versuchte damit, ein kleineres Skript zu erstellen.Hinweis: Nicht alle Kompositionen verwenden einen Joiner mit einer Breite von Null, sodass er mit anderen Kompositionszeichen fehlerhaft ist.
Es verwendet die traditionelle
for
Schleife, da wir einige Iterationen überspringen, falls wir kombinierte Emoticons finden. Innerhalb derfor
Schleife gibt es einewhile
Schleife, um zu überprüfen, ob ein folgendes\u200d
Zeichen vorhanden ist. Solange es eines gibt, fügen wir auch die nächsten 2 Zeichen hinzu und leiten diefor
Schleife mit 2 Iterationen weiter, damit kombinierte Emoticons nicht umgekehrt werden.Um es einfach für jede Zeichenfolge zu verwenden, habe ich es als neue Prototypfunktion für das Zeichenfolgenobjekt erstellt.
String.prototype.reverse = function() { let textArray = [...this]; let reverseString = ""; for (let i = 0; i < textArray.length; i++) { let char = textArray[i]; while (textArray[i + 1] === '\u200d') { char += textArray[i + 1] + textArray[i + 2]; i = i + 2; } reverseString = char + reverseString; } return reverseString; } const text = "Hello world👩🦰👩👩👦👦"; console.log(text.reverse()); //Fun fact, you can chain them to double reverse :) //console.log(text.reverse().reverse());
quelle
👩👩👦👦
kann er nur als Ganzes ausgewählt werden. Woher wissen Browser, dass es sich um ein Zeichen handelt? Gibt es eine eingebaute Möglichkeit, dies zu tun?Das Umkehren von Unicode-Text ist aus vielen Gründen schwierig.
Erstens werden Zeichenfolgen je nach Programmiersprache auf unterschiedliche Weise dargestellt, entweder als Liste von Bytes, als Liste von UTF-16-Codeeinheiten (16 Bit breit, in der API häufig als "Zeichen" bezeichnet) oder als ucs4-Codepunkte (4 Bytes breit).
Zweitens spiegeln verschiedene APIs diese innere Repräsentation in unterschiedlichem Maße wider. Einige arbeiten an der Abstraktion von Bytes, andere an UTF-16-Zeichen, andere an Codepunkten. Wenn die Darstellung Bytes oder UTF-16-Zeichen verwendet, gibt es normalerweise Teile der API, die Ihnen Zugriff auf die Elemente dieser Darstellung gewähren, sowie Teile, die die erforderliche Logik ausführen, um von Bytes (über UTF-8) oder von zu erhalten UTF-16-Zeichen zu den tatsächlichen Codepunkten.
Oft wurden die Teile der API, die diese Logik ausführen und Ihnen so Zugriff auf die Codepunkte gewähren, später hinzugefügt, da zuerst 7-Bit-ASCII vorhanden waren, dann etwas später alle dachten, 8-Bit wären ausreichend, wobei verschiedene Codeseiten verwendet wurden, und sogar später reichten 16 Bit für Unicode. Der Begriff der Codepunkte als Ganzzahlen ohne feste Obergrenze wurde historisch als vierte gemeinsame Zeichenlänge für die logische Codierung von Text hinzugefügt.
Die Verwendung einer API, mit der Sie auf die tatsächlichen Codepunkte zugreifen können, scheint das Richtige zu sein. Aber...
Drittens gibt es viele Modifikatorcodepunkte, die den nächsten Codepunkt oder die folgenden Codepunkte beeinflussen. Zum Beispiel gibt es einen diakritischen Modifikator, der aus einem folgenden a ein ä, e nach ë usw. macht. Drehen Sie die Codepunkte um und aë wird zu eä, bestehend aus verschiedenen Buchstaben. Es gibt eine direkte Darstellung von zB ä als eigenen Codepunkt, aber die Verwendung des Modifikators ist genauso gültig.
Viertens ist alles in ständigem Fluss. Es gibt auch viele Modifikatoren unter den Emoji, wie im Beispiel verwendet, und jedes Jahr werden weitere hinzugefügt. Wenn Sie über eine API auf die Informationen zugreifen können, ob ein Codepunkt ein Modifikator ist, bestimmt die Version der API, ob sie bereits einen bestimmten neuen Modifikator kennt.
Unicode bietet jedoch einen hackigen Trick, wenn es nur um das visuelle Erscheinungsbild geht:
Es gibt Modifikatoren für die Schreibrichtung. Im Beispiel wird die Schreibrichtung von links nach rechts verwendet. Fügen Sie am Anfang des Textes einfach einen Modifikator für die Schreibrichtung von rechts nach links hinzu. Abhängig von der Version der API / des Browsers sieht dieser korrekt umgekehrt aus 😎
'\ u202e' heißt Override von rechts nach links, es ist die stärkste Version der Markierung von rechts nach links.
Siehe diese Erklärung von w3.org
const text = 'Hello world👩🦰👩👩👦👦' console.log('\u202e' + text)
const text = 'Hello world👩🦰👩👩👦👦' let original = document.getElementById('original') original.appendChild(document.createTextNode(text)) let result = document.getElementById('result') result.appendChild(document.createTextNode('\u202e' + text))
body { font-family: sans-serif }
<p id="original"></p> <p id="result"></p>
quelle
'\u202e' + text + '\u202c'
zu schließen, um die Beeinflussung des folgenden Textes zu vermeiden.Ich kenne! Ich werde RegExp verwenden. Was könnte schiefgehen? (Antwort links als Übung für den Leser.)
const text = 'Hello world👩🦰👩👩👦👦'; const reversed = text.match(/.(\u200d.)*/gu).reverse().join(''); console.log(reversed);
quelle
.
Platzhalter).U+200D
z🏳️🌈
. Es ist erwähnenswert, dass komponierte Charaktere auch außerhalb der Emijoi-Welt existieren…U+200D
. Es ist leicht zu überprüfen, ob 🏳️🌈 mit dem Code dieser Antwort nicht funktioniert…Eine alternative Lösung wäre die Verwendung einer
runes
kleinen, aber effektiven Bibliothek:https://github.com/dotcypress/runes
const runes = require('runes') // String.substring '👨👨👧👧a'.substring(1) => '�👨👧👧a' // Runes runes.substr('👨👨👧👧a', 1) => 'a' runes('12👩👩👦👦3🍕✓').reverse().join(); // results in: "✓🍕3👩👩👦👦21"
quelle
Sie haben nicht nur Probleme mit Emoji, sondern auch mit anderen kombinierenden Charakteren. Diese Dinge, die sich wie einzelne Buchstaben anfühlen, aber tatsächlich ein oder mehrere Unicode-Zeichen sind, werden als "erweiterte Graphemcluster" bezeichnet.
Das Aufteilen einer Zeichenfolge in diese Cluster ist schwierig (siehe beispielsweise diese Unicode-Dokumente ). Ich würde mich nicht darauf verlassen, es selbst zu implementieren, sondern eine vorhandene Bibliothek verwenden. Google hat mich auf die Graphem-Splitter- Bibliothek hingewiesen . Die Dokumente für diese Bibliothek enthalten einige nette Beispiele , die die meisten Implementierungen auslösen werden:
Damit sollten Sie schreiben können:
var splitter = new GraphemeSplitter(); var graphemes = splitter.splitGraphemes(string); var reversed = graphemes.reverse().join('');
ASIDE: Für Besucher aus der Zukunft oder diejenigen, die bereit sind, auf dem neuesten Stand zu leben:
Es wird vorgeschlagen , dem Javascript-Standard einen Graphemsegmentierer hinzuzufügen. (Es bietet auch andere Segmentierungsoptionen). Es befindet sich derzeit in Phase 3 und wird derzeit in JSC und V8 implementiert (siehe https://github.com/tc39/proposal-intl-segmenter/issues/114 ).
Mit diesem würde der Code wie folgt aussehen:
var segmenter = new Intl.Segmenter("en", {granularity: "grapheme"}) var segment_iterator = segmenter.segment(string) var graphemes = [] for (let {segment} of segment_iterator) { graphemes.push(segment) } var reversed = graphemes.reverse().join('');
Sie können dies wahrscheinlich ordentlicher machen, wenn Sie moderneres Javascript kennen als ich ...
Hier gibt es eine Implementierung - aber ich weiß nicht, was es erfordert.
Hinweis: Dies weist auf ein unterhaltsames Problem hin, das andere Antworten noch nicht angesprochen haben. Die Segmentierung kann vom verwendeten Gebietsschema abhängen - nicht nur von den Zeichen in der Zeichenfolge.
quelle
const graphemes = Array.from(segment_iterator, ({segment}) => segment)
.Ich habe mich nur zum Spaß dafür entschieden, war eine gute Herausforderung. Nicht sicher, ob es in allen Fällen korrekt ist. Verwenden Sie es daher auf eigenes Risiko. Hier ist es jedoch:
function run() { const text = 'Hello world👩🦰👩👩👦👦'; const newText = reverseText(text); console.log(newText); } function reverseText(text) { // first, create an array of characters let textArray = [...text]; let lastCharConnector = false; textArray = textArray.reduce((acc, char, index) => { if (char.charCodeAt(0) === 8205) { const lastChar = acc[acc.length-1]; if (Array.isArray(lastChar)) { lastChar.push(char); } else { acc[acc.length-1] = [lastChar, char]; } lastCharConnector = true; } else if (lastCharConnector) { acc[acc.length-1].push(char); lastCharConnector = false; } else { acc.push(char); lastCharConnector = false; } return acc; }, []); console.log('initial text array', textArray); textArray = textArray.reverse(); console.log('reversed text array', textArray); textArray = textArray.map((item) => { if (Array.isArray(item)) { return item.join(''); } else { return item; } }); return textArray.join(''); } run();
quelle
Sie können verwenden:
yourstring.split('').reverse().join('')
Es sollte Ihre Zeichenfolge in eine Liste verwandeln, sie umkehren und dann wieder zu einer Zeichenfolge machen.
quelle
const text = 'Hallo Welt👩🦰👩👩👦👦';
const reverse = text.split (''). reverse (). join ('');
console.log (umgekehrt);
quelle