Wie kann ich jeden Textbuchstaben mit Javascript verarbeiten?

361

Ich möchte jeden einzelnen Buchstaben einer Zeichenfolge benachrichtigen, bin mir aber nicht sicher, wie ich das tun soll.

Also, wenn ich habe:

var str = 'This is my string';

Ich möchte T, h, i, s usw. separat benachrichtigen können. Dies ist nur der Anfang einer Idee, an der ich arbeite, aber ich muss wissen, wie jeder Buchstabe separat verarbeitet wird.

Ich möchte jQuery verwenden und dachte, ich müsste möglicherweise die Split-Funktion verwenden, nachdem ich die Länge der Zeichenfolge getestet habe.

Ideen?

Nic Hubbard
quelle
3
Vielleicht haben Sie danach gesucht: Ab ES6 gibt es for(const c of str) { ... }. Mehr davon weiter unten in einer recht detaillierten, aber nicht ausreichend bewerteten Antwort. PS: @ ARJUNs Link funktioniert bei mir nicht.
Max

Antworten:

419

Wenn die Reihenfolge der Warnungen von Bedeutung ist, verwenden Sie Folgendes:

for (var i = 0; i < str.length; i++) {
  alert(str.charAt(i));
}

Wenn die Reihenfolge der Warnungen keine Rolle spielt, verwenden Sie Folgendes:

var i = str.length;
while (i--) {
  alert(str.charAt(i));
}

Eli Gray
quelle
2
Die Verwendung von [], um das Zeichen an eine bestimmte Position zu bringen, wird in IE <9
vsync
13
Wie in der anderen Antwort beschrieben, können Sie str.charAt (i) anstelle der [] verwenden. Weitere Informationen darüber, warum Sie charAt vs [] verwenden sollten, finden Sie unter string.charAt (x) oder string [x]
Julian Soro,
12
Es fällt mir schwer zu glauben, dass ein moderner JS-Compiler die Länge neu berechnen würde, wenn der String nicht innerhalb der Schleife geändert wurde. In jeder anderen Sprache würde ich gerne die Längenprüfung in der Testklausel der for-Schleife durchführen, vorausgesetzt, der Compiler weiß es am besten und würde es entsprechend optimieren.
Echelon
3
@Dagmar: Javascript verwendet nicht UTF-8, sondern UTF-16 (oder UCS-2, je nach Browser). Jedes einzelne Zeichen kann entweder als UTF-8 oder UTF-16 dargestellt werden, hat jedoch dieses Problem nicht. Die einzigen, die das Problem haben, sind diejenigen, die vier Bytes in UTF-16 anstelle von zwei Bytes benötigen. 💩 ist ein Zeichen, das in UTF-16 vier Bytes benötigt. Wichtige Begriffe, um nach weiteren Informationen zu suchen, sind "Astralebene", "Nicht-BMP" und "Ersatzpaar".
Hippietrail
1
@Dagmar: Java und Javascript haben beide UTF-16 (früher UCS-) gemeinsam. Die dritte wichtige Plattform, die es verwendet, ist Windows. Unix-, MacOS- und Internetprotokolle verwenden UTF-8. charAtist von den UCS-2-Tagen übrig geblieben, als es keine Ersatzpaare gab, und um das Problem zu lösen, codepointAtwurde JavaScript eine neue Funktion hinzugefügt, die unseren freundlichen Haufen Kot korrekt behandelt. Ich glaube, Java hat es auch.
Hippietrail
240

Es ist wahrscheinlich mehr als gelöst. Ich möchte nur mit einer anderen einfachen Lösung einen Beitrag leisten:

var text = 'uololooo';

// With ES6
[...text].forEach(c => console.log(c))

// With the `of` operator
for (const c of text) {
    console.log(c)
}

// With ES5
for (var x = 0, c=''; c = text.charAt(x); x++) { 
    console.log(c); 
}

// ES5 without the for loop:
text.split('').forEach(function(c) {
    console.log(c);
});
Herr Goferito
quelle
4
Das letzte Beispiel kann einfach sein[...text].forEach(console.log)
Govind Rai
10
Nein, das kann es nicht. forEach()Übergibt den Index und das Array als zweites und drittes Argument. Ich würde das lieber nicht protokollieren ..
Mr. Goferito
1
Beachten Sie, dass sowohl der Spread-Operator (erstes Beispiel) als auch der Split-Aufruf (letztes Beispiel) ein neues Array erstellen. Dies ist normalerweise kein Problem, kann jedoch für große Zeichenfolgen oder häufige Anwendungen kostspielig sein.
Randolpho
Was ist mitfor (let c of [...text]) { console.log(c) }
Flimm
Damit erstellen Sie ein neues Array aus der Zeichenfolge. Ich sehe den Nutzen nicht. let c of textmacht den Job schon.
Herr Goferito
73

Eine mögliche Lösung in reinem Javascript:

for (var x = 0; x < str.length; x++)
{
    var c = str.charAt(x);
    alert(c);
}
miku
quelle
Es wäre wahrscheinlich besser mit var x = 0 und var c = str.charAt (x).
Rich
2
Außerdem sollte str.length in einer Variablen gespeichert werden, damit nicht ständig darauf zugegriffen werden muss.
Eli Gray
8
@EliGrey Ist es wirklich so wichtig, die Länge in eine Variable zu setzen? Haben Sie Benchmarks, bei denen dies weniger Codezeilen vorzuziehen wäre?
pm_labs
@paul_sns Interessanterweise scheint es zumindest in Edge einen geringfügigen Unterschied zu geben (0,7 ms Unterschied für ein Array mit 10000 Elementen): jsfiddle.net/carcigenicate/v8vvjoc1/1 . Wahrscheinlich kein perfekter Test, aber er basiert auf durchschnittlich 10000 Tests.
Carcigenicate
1
@paul_sns Interessanterweise hat Chrome in etwa 2% der Fälle denselben Test durchgeführt (~ 5 ms gegenüber ~ 0,0997 ms), und beide Versionen haben dieselbe Zeit angegeben, sodass Edge anscheinend nicht optimiert ist.
Carcigenicate
69

So verarbeiten Sie jeden Textbuchstaben (mit Benchmarks)

https://jsperf.com/str-for-in-of-foreach-map-2

zum

Klassisch und bei weitem derjenige mit der höchsten Leistung . Sie sollten sich für diesen entscheiden, wenn Sie ihn in einem leistungskritischen Algorithmus verwenden möchten oder wenn er die maximale Kompatibilität mit Browserversionen erfordert.

for (var i = 0; i < str.length; i++) {
  console.info(str[i]);
}

für ... von

for ... of ist der neue ES6 für Iterator. Unterstützt von den meisten modernen Browsern. Es ist optisch ansprechender und weniger anfällig für Tippfehler. Wenn Sie diesen in einer Produktionsanwendung verwenden, sollten Sie wahrscheinlich einen Transpiler wie Babel verwenden .

let result = '';
for (let letter of str) {
  result += letter;
}

für jedes

Funktionaler Ansatz. Airbnb genehmigt . Der größte Nachteil dabei ist split(), dass ein neues Array erstellt wird, in dem jeder einzelne Buchstabe der Zeichenfolge gespeichert wird.

Warum? Dies setzt unsere unveränderliche Regel durch. Der Umgang mit reinen Funktionen, die Werte zurückgeben, ist leichter zu begründen als Nebenwirkungen.

// ES6 version.
let result = '';
str.split('').forEach(letter => {
  result += letter;
});

oder

var result = '';
str.split('').forEach(function(letter) {
  result += letter;
});

Das Folgende sind diejenigen, die ich nicht mag.

für in

Im Gegensatz zu für ... von erhalten Sie den Buchstabenindex anstelle des Buchstabens. Es funktioniert ziemlich schlecht.

var result = '';
for (var letterIndex in str) {
  result += str[letterIndex];
}

Karte

Funktionsansatz, der gut ist. Die Karte ist jedoch nicht dafür gedacht. Es sollte verwendet werden, wenn die Werte innerhalb eines Arrays geändert werden müssen, was nicht der Fall ist.

// ES6 version.
var result = '';
str.split('').map(letter => {
  result += letter;
});

oder

let result = '';
str.split('').map(function(letter) {
  result += letter;
});
zurfyx
quelle
1
Auf meiner Maschine war die klassische forSchleife tatsächlich die zweitlangsamste und for...ofdie schnellste (ungefähr dreimal so schnell wie for).
John Montgomery
1
Wo ist der Benchmark? Was ist die schnellste Lösung?
Poitroae
1
@johnywhy Das war vor zwei Jahren und der Link ist tot. Ich bin mir nicht sicher, wie Sie erwarten, dass ich das Ergebnis verteidige, das ich damals erzielt habe. Das Einrichten eines neuen Benchmarks stimmt nun jedoch mit der Schlussfolgerung von zurfyx überein, wobei die forSchleife etwas schneller ist.
John Montgomery
1
@ JohnMontgomery Ich erwarte nicht, dass du etwas tust. Nur ein Hinweis für zukünftige Leser, dass Ihre Ergebnisse anders sind als die Antwort. Ich persönlich würde gerne wissen, welche Ergebnisse heute 2020 für Browser gelten, obwohl 2018 noch nicht so lange her ist. Welcher Link ist tot?
Johny, warum
1
@johnywhy Der Link oben mit allen aktuellen Tests gibt mir einen 404 zurück.
John Montgomery
42

Die meisten, wenn nicht alle Antworten hier sind falsch, da sie unterbrochen werden, wenn sich ein Zeichen in der Zeichenfolge außerhalb des Unicode-BMP (Basic Multilingual Plane) befindet . Das bedeutet, dass alle Emoji kaputt sind .

JavaScript verwendet UTF- 16- Unicode für alle Zeichenfolgen. In UTF-16, Zeichen jenseits der BMP sind aus aus zwei Teilen, einem „genannt Surrogate Pair “ und die meisten Antworten hier wird verarbeiten jedes Teil solcher Paare einzeln statt als ein einzelnes Zeichen.

Eine Möglichkeit in modernem JavaScript seit mindestens 2016 ist die Verwendung des neuen String-Iterators . Hier ist das Beispiel (fast) direkt aus MDN:

var string = 'A\uD835\uDC68B\uD835\uDC69C\uD835\uDC6A';

for (var v of string) {
  alert(v);
}
// "A"
// "\uD835\uDC68"
// "B"
// "\uD835\uDC69"
// "C"
// "\uD835\uDC6A"

Hippietrail
quelle
4
Eine moderne Lösung zum Aufteilen einer Zeichenfolge in Zeichen unter Berücksichtigung von Ersatzpaaren finden
hippietrail
20

Sie können dies versuchen

var arrValues = 'This is my string'.split('');
// Loop over each value in the array.
$.each(arrValues, function (intIndex, objValue) {
    alert(objValue);
})
Adriaan Stander
quelle
11
Immer noch ist eine Option, aber nicht performant. Setzen Sie jQuery nicht überall ein.
Cagatay
10

Noch eine Lösung ...

var strg= 'This is my string';
for(indx in strg){
  alert(strg[indx]);
}
Pamsix
quelle
3
Wenn Sie nur das Zeichen und nicht den Index wollen, wäre es schneller, eine for..ofSchleife zu verwendenfor (let ch of t) { alert(ch) }
Shaheen Ghiassy
10

Wenn ich einen Kurzcode oder einen Einzeiler schreiben muss, verwende ich diesen "Hack":

'Hello World'.replace(/./g, function (char) {
    alert(char);
    return char; // this is optional 
});

Dies zählt keine Zeilenumbrüche, so dass dies eine gute oder eine schlechte Sache sein kann. Wenn Sie Zeilenumbrüche einfügen möchten, ersetzen Sie: /./durch /[\S\s]/. Die anderen Einzeiler Sie sehen wahrscheinlich möglicherweise verwenden , .split()die viele Probleme hat

Downgoat
quelle
beste Antwort. Berücksichtigt Probleme mit Unicode und kann auch mit funktionalen Konstrukten mit .map () usw. verwendet werden
Rofrol
Das einzige, was ich an diesem nicht mag, ist, wenn ich Zugriff auf die zusätzlichen Parameter habenforEach möchte, die an die Funktion des Aufrufs übergeben werden, im Vergleich zu den gesendeten Parameternreplace . Wenn ich weiß, dass ich ASCIIing bin, denke ich, dass ich noch einige Anwendungsfälle für habe split. Tolle Antwort!
Ruffin
Diese Antwort hat den Bonus, die Werte
vorzuwählen
1
Ich dachte, dies würde die Unicode-Probleme nicht berücksichtigen, wenn es nicht die uFlagge zusammen mit der gFlagge hätte? OK, gerade getestet und ich hatte recht.
Hippietrail
9

New JS erlaubt dies:

const str = 'This is my string';
Array.from(str).forEach(alert);
Papajson
quelle
8

Aufgrund der unterschiedlichen Bytegröße ist es besser, die Anweisung for ... of zu verwenden, wenn die Zeichenfolge Unicode-Zeichen enthält.

for(var c of "tree 木") { console.log(c); }
//"𝐀A".length === 3
Martin Wantke
quelle
7

kurze Antwort: Array.from(string)gibt Ihnen, was Sie wahrscheinlich wollen, und dann können Sie darauf iterieren oder was auch immer, da es nur ein Array ist.

ok lass es uns mit dieser Zeichenfolge versuchen : abc|⚫️\n⚪️|👨‍👩‍👧‍👧.

Codepunkte sind:

97
98
99
124
9899, 65039
10
9898, 65039
124
128104, 8205, 128105, 8205, 128103, 8205, 128103

Einige Zeichen haben also einen Codepunkt (Byte) und einige zwei oder mehr, und eine neue Zeile wurde für zusätzliche Tests hinzugefügt.

Nach dem Testen gibt es also zwei Möglichkeiten:

  • Byte pro Byte (Codepunkt pro Codepunkt)
  • Charaktergruppen (aber nicht die ganze Familie Emoji)

string = "abc|⚫️\n⚪️|👨‍👩‍👧‍👧"

console.log({ 'string': string }) // abc|⚫️\n⚪️|👨‍👩‍👧‍👧
console.log({ 'string.length': string.length }) // 21

for (let i = 0; i < string.length; i += 1) {
  console.log({ 'string[i]': string[i] }) // byte per byte
  console.log({ 'string.charAt(i)': string.charAt(i) }) // byte per byte
}

for (let char of string) {
  console.log({ 'for char of string': char }) // character groups
}

for (let char in string) {
  console.log({ 'for char in string': char }) // index of byte per byte
}

string.replace(/./g, (char) => {
  console.log({ 'string.replace(/./g, ...)': char }) // byte per byte
});

string.replace(/[\S\s]/g, (char) => {
  console.log({ 'string.replace(/[\S\s]/g, ...)': char }) // byte per byte
});

[...string].forEach((char) => {
  console.log({ "[...string].forEach": char }) // character groups
})

string.split('').forEach((char) => {
  console.log({ "string.split('').forEach": char }) // byte per byte
})

Array.from(string).forEach((char) => {
  console.log({ "Array.from(string).forEach": char }) // character groups
})

Array.prototype.map.call(string, (char) => {
  console.log({ "Array.prototype.map.call(string, ...)": char }) // byte per byte
})

var regexp = /(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/g

string.replace(regexp, (char) => {
  console.log({ 'str.replace(regexp, ...)': char }) // character groups
});

localhostdotdev
quelle
7

Sie können jetzt einzelne Unicode-Codepunkte durchlaufen, die in einem String enthalten sind, indem Sie String.prototype[@@iterator]einen Wert des bekannten Symboltyps zurückgeben Symbol.iterator- den Standarditerator für Array-ähnliche Objekte ( Stringin diesem Fall).

Beispielcode:

const str = 'The quick red 🦊 jumped over the lazy 🐶! 太棒了!';

let iterator = str[Symbol.iterator]();
let theChar = iterator.next();

while(!theChar.done) {
  console.log(theChar.value);
  theChar = iterator.next();
}

// logs every unicode character as expected into the console.

Dies funktioniert mit Unicode-Zeichen wie Emoji oder nicht-römischen Zeichen, die ältere Konstrukte auslösen würden.

Referenz: MDN-Link zu String.prototype @@ iterator .

Aditya MP
quelle
2
Beachten Sie, dass Sie dies auch mit einer for ... ofSchleife über der Zeichenfolge kürzer tun können - das ist Syntaxzucker für den Zugriff auf den Iterator.
Aditya MP
6

Sie können jetzt in Schlüsselwort verwenden.

    var s = 'Alien';
    for (var c in s) alert(s[c]);

mih0vil
quelle
Die Verwendung in ist eine schlechte Übung und schrecklich, wenn sie ungefiltert ist. Ich
rate
4
@ Downgoat warum? Was ist daran schlecht? Ich meine, wenn ich in einer Situation bin, in der ich weiß, dass 'in' von meiner Javascript-Engine unterstützt wird und mein Code nicht in eine andere Engine gelangt ... warum nicht?
TKoL
@TKoL Sehen Sie dies .
Alan
@ Alan inist ein legitimer Teil der Sprache. Verwenden Sie die Dinge angemessen. In Ihrem Artikel wird darauf hingewiesen, dass Alphatasten ingenauso wie Zifferntasten interpretiert werden. Damit? Vielleicht ist es das, was du willst. Man könnte auch sagen, dass andere Methoden Alpha-Schlüssel fälschlicherweise ignorieren. Imo, ofhat korrektes Verhalten. In JS-Arrays haben Elemente ohne Alpha-Schlüssel weiterhin Schlüssel: numerische. In meiner Konsole behandelt JS die Alpha-Taste "korrekt" wie die Zifferntasten:>const arr = ['a', 'b'] >arr.test = 'hello' >arr 0: "a" 1: "b" test: "hello" length: 2
Johny, warum
5

Sie können ein Array der einzelnen Zeichen wie folgt erhalten

var test = "test string",
    characters = test.split('');

und dann eine Schleife mit normalem Javascript ausführen, oder Sie können die Zeichen der Zeichenfolge mit jQuery von durchlaufen

var test = "test string";

$(test.split('')).each(function (index,character) {
    alert(character);
});
Reich
quelle
5

Sie können diese Zeichenfolge mithilfe von in ein Array von Zeichen konvertieren split()und dann durchlaufen.

const str = "javascript";
const strArray = str.split('');

strArray.map(s => console.log(s));

Muhammed Moussa
quelle
Anscheinend schlägt dies mit Unicode-Zeichen und Grafiksymbolen fehl.
Johny, warum
4

Wenn Sie den Text auf Zeichenebene transformieren und den transformierten Text am Ende zurückerhalten möchten, gehen Sie folgendermaßen vor:

var value = "alma";
var new_value = value.split("").map(function(x) { return x+"E" }).join("")

Also die Schritte:

  • Teilen Sie die Zeichenfolge in ein Array (eine Liste) von Zeichen auf
  • Ordne jeden Charakter über einen Funktor zu
  • Verbinden Sie das resultierende Zeichenarray zu der resultierenden Zeichenfolge
Vajk Hermecz
quelle
0

Im heutigen JavaScript können Sie

Array.prototype.map.call('This is my string', (c) => c+c)

Offensichtlich steht c + c für alles, was Sie mit c machen möchten.

Dies kehrt zurück

["TT", "hh", "ii", "ss", " ", "ii", "ss", " ", "mm", "yy", " ", "ss", "tt", "rr", "ii", "nn", "gg"]

Pum Walters
quelle
Möglicherweise:[...'This is my string'].map((c)=>c+c)
Alan
0

Dies sollte in älteren Browsern und mit UTF-16-Zeichen wie 💩 funktionieren.

Dies sollte die am besten kompatible Lösung sein. Es ist jedoch weniger performant als eine forSchleife.

Ich habe den regulären Ausdruck mit regexpu generiert

var str = 'My String 💩 ';
var regEx = /(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/g


str.replace(regEx, function (char) {
    console.log(char)
});

Hoffe das hilft!

Ben Gubler
quelle
Was meinst du mit "weniger perfomant"? Ich denke, Sie meinen "langsamer", da es den Anforderungen besser entspricht und eine gute Leistung erbringt.
Hippietrail
-1

Sie können mit oder auf einzelne Zeichen zugreifen . Der letztere Weg ist jedoch nicht Teil von ECMAScript, daher sollten Sie sich besser für den ersteren entscheiden.str.charAt(index)str[index]

Gumbo
quelle
Ich würde mich davon fernhalten. Leider funktioniert das nicht in allen IE-Versionen. Vertrau mir. Ich habe es auf die harte Tour gelernt.
Xavi
3
Es ist Teil von ECMAScript, jedoch nur in der neu veröffentlichten 5. Ausgabe, nicht in der 3 ..
Kangax
-1

Wenn Sie jedes Zeichen animieren möchten, müssen Sie es möglicherweise in ein span-Element einschließen.

var $demoText = $("#demo-text");
$demoText.html( $demoText.html().replace(/./g, "<span>$&amp;</span>").replace(/\s/g, " "));

Ich denke, dies ist der beste Weg, dies zu tun und dann die Spannweiten zu verarbeiten. (zum Beispiel mit TweenMax)

TweenMax.staggerFromTo ($ demoText.find ("span"), 0,2, {autoAlpha: 0}, {autoAlpha: 1}, 0,1);

Chris Panayotoff
quelle
-1

Versuchen Sie diesen Code

    function myFunction() {
    var text =(document.getElementById("htext").value); 
    var meow = " <p> <,> </p>";
    var i;


    for (i = 0; i < 9000; i++) {

        text+=text[i] ;



    }

    document.getElementById("demo2").innerHTML = text;

}
</script>
<p>Enter your text: <input type="text" id="htext"/>

    <button onclick="myFunction();">click on me</button>
</p>
Miau
quelle