Wir haben alle in unserer Schulzeit Aufsätze geschrieben. Es gab immer eine Mindestwortanzahl – 250, 500 Wörter –, die wir vor der Abgabe erreichen mussten. Bevor ich zu Hause einen Computer hatte, habe ich Wörter manuell gezählt. Als meine Eltern mir einen besorgten, war die Entdeckung von Microsoft Word wie Magie. Ich konnte damals nicht programmieren, daher war ich von allem, was MS Word tat, fasziniert.
Eine der Funktionen, die mir sehr gut gefiel, hieß „Wortanzahl“. Man konnte einen beliebigen Text auswählen und auf Extras > Wortanzahl klicken, um interessante Statistiken wie die Anzahl der Zeichen, Wörter und Absätze zu Ihrem ausgewählten Text zu erhalten. Das hat mir damals gefallen, und ich nutze es sogar jetzt gerade, während ich diesen Artikel in Google Tabellen entwerfe. Ich dachte mir, ich versuche mal, selbst eine zu schreiben.
Die App, die wir heute machen werden, wird Folgendes berechnen:
- Anzahl der Zeichen, Wörter und Sätze in einem Text
- Top verwendete Schlüsselwörter
- Lesbarkeits-Score – wie schwierig es ist, den Abschnitt zu verstehen.
Bevor wir beginnen, können Sie hier sehen, was wir machen
Sehen Sie sich den Pen Word Counter von Vikas Lalwani (@lalwanivikas) auf CodePen an.
Jetzt legen wir los!
Die gesamte Zählung in der App basiert stark auf regulären Ausdrücken (im Rest des Artikels als „Regex“ bezeichnet). Wenn Sie mit Regex nicht vertraut sind, lesen Sie diesen Anfängerartikel über reguläre Ausdrücke in JavaScript.
Seitenaufbau
Zuerst und vor allem brauchen wir etwas, um Benutzereingaben entgegenzunehmen. Was gibt es Besseres, als ein textarea HTML-Element?
<textarea placeholder="Enter your text here..."></textarea>
Wir können den obigen Textbereich mit diesem JavaScript-Code auswählen
var input = document.querySelectorAll('textarea')[0];
Wir können den Eingabestring über input.value abrufen. Da wir die Statistiken anzeigen möchten, während der Benutzer tippt, müssen wir unsere Logik bei keyup ausführen. So sieht das Grundgerüst unserer Kernlogik aus
input.addEventListener('keyup', function() {
// word counter logic
// sentence count logic
// reading time calculation
// keyword finding logic
});
Die Ausgabe wird in einfachen HTML-div-Elementen gespeichert, also nichts Besonderes
<div class="output row">
<div>Characters: <span id="characterCount">0</span></div>
<div>Words: <span id="wordCount">0</span></div>
</div>
<!-- more similar divs for other stats -->
Teil 1: Zählen von Zeichen und Wörtern
Nachdem das grundlegende Setup erledigt ist, schauen wir uns an, wie man Wörter und Sätze zählt. Eine der besten Methoden dafür ist die Verwendung von Regex.
Ich werde Sie durch die Regex-Muster für die Wort- und Satzzählung führen. Sobald Sie das verstanden haben, können Sie den Rest selbst herausfinden, indem Sie sich den Quellcode ansehen.
Wir müssen zwei Dinge suchen, um Wörter in unserem Eingabestring zu finden
- Wortgrenzen
- gültige Wortzeichen
Wenn wir diese finden können, erhalten wir unsere Wortliste. Eine weitere Möglichkeit, die Genauigkeit zu erhöhen, ist die Suche nach Bindestrichen (-). So werden Wörter mit Bindestrichen (z. B. CSS-Tricks) als ein Wort gezählt und nicht als 2 oder mehr.
var words = input.value.match(/\b[-?(\w+)?]+\b/gi);
Im obigen Muster
\bstimmt mit Wortgrenzen überein, d. h. Anfang oder Ende eines Wortes\w+stimmt mit Wortzeichen überein.+sorgt dafür, dass ein oder mehrere Zeichen übereinstimmen-?stimmt mit Bindestrichen überein, das?am Ende macht es optional. Dies ist ein Sonderfall für die Zählung von Wörtern mit Bindestrichen als ein Wort. Zum Beispiel werden ‚long-term‘ und ‚front-end‘ als ein Wort und nicht als zwei gezählt+am Ende des Musters stimmt mit einem oder mehreren Vorkommen des gesamten Musters überein- Schließlich macht
ies Groß-/Kleinschreibung unabhängig, undgführt eine globale Suche durch, anstatt beim ersten Treffer anzuhalten
Als Nächstes untersuchen wir, wie man Sätze zählt.
Sätze sind relativ einfach zu handhaben, da wir nur Satzzeichen erkennen und dort aufteilen müssen. So sieht der Code dafür aus
var sentences = input.value.split(/[.|!|?]/g);
Im obigen Muster suchen wir nach drei Zeichen – ., ! und ? – im Eingabetext, da diese drei als Satzzeichen verwendet werden.
Nach der obigen Operation enthält sentences ein Array aller Sätze. Aber es gibt einen interessanten Fall, den wir berücksichtigen müssen, bevor wir zählen: Was ist, wenn jemand „come back soon…“ eingibt?
Basierend auf der obigen Logik enthält sentences vier Einträge – einen korrekten Satz und drei leere Strings. Aber das ist nicht das, was wir wollen. Eine Möglichkeit, dies zu lösen, ist, das obige Regex-Muster wie folgt zu ändern:
var sentences = input.value.split(/[.|!|?]+/g);
Beachten Sie das + am Ende des Musters. Es dient dazu, Fälle zu berücksichtigen, in denen ein Benutzer aufeinanderfolgende Satzzeichen eingibt. Mit dieser Änderung wird „come back soon…“ als ein Satz und nicht als vier gezählt.
Wenn Sie der obigen Erklärung zum Zählen von Wörtern und Sätzen gefolgt sind, können Sie den Rest der Logik selbst verstehen, indem Sie sich den Quellcode ansehen. Wichtig ist, Randfälle nicht zu vergessen, wie Wörter mit Bindestrichen und leere Sätze.
Teil 2: Finden der Top-Schlüsselwörter
Sobald Sie zu tippen beginnen, werden Sie feststellen, dass am unteren Rand der Seite ein neuer Container erscheint, der die Top-Schlüsselwörter des Textes anzeigt. Dies zeigt Ihnen, welche Schlüsselwörter Sie am häufigsten verwendet haben, was Ihnen helfen kann, die übermäßige Verwendung bestimmter Wörter in Ihrem Schreiben zu vermeiden. Das ist cool, aber wie berechnen wir das?
Um die Berechnung von Top-Schlüsselwörtern besser verständlich zu machen, habe ich den Prozess in folgende 4 Schritte unterteilt:
- Entfernen aller Stoppwörter
- Erstellen eines Objekts mit Schlüsselwörtern und ihrer Anzahl
- Sortieren des Objekts durch Umwandlung in ein 2D-Array
- Anzeigen der Top 4 Schlüsselwörter und ihrer Anzahl
Schritt 1) Alle Stoppwörter entfernen
Stoppwörter sind die häufigsten Wörter in einer Sprache, und wir müssen sie herausfiltern, bevor wir eine Analyse unseres Textes durchführen. Leider gibt es keine universelle Liste von Stoppwörtern, aber eine einfache Suche wird Ihnen viele Optionen liefern. Wählen Sie einfach eine aus und machen Sie weiter.
Dies ist der Code zum Herausfiltern von Stoppwörtern (Erklärung unten)
// Step 1) removing all the stop words
var nonStopWords = [];
var stopWords = ["a", "able", "about", "above", ...];
for (var i = 0; i < words.length; i++) {
// filtering out stop words and numbers
if (stopWords.indexOf(words[i].toLowerCase()) === -1 && isNaN(words[i])) {
nonStopWords.push(words[i].toLowerCase());
}
}
Das stopWords-Array enthält alle Wörter, mit denen wir abgleichen müssen. Wir durchlaufen unser words-Array und prüfen, ob jeder Eintrag im stopWords-Array vorhanden ist. Wenn ja, ignorieren wir ihn. Wenn nicht, fügen wir ihn zum nonStopWords-Array hinzu. Wir ignorieren auch alle Zahlen (daher die Bedingung isNaN).
Schritt 2) Erstellen eines Objekts mit Schlüsselwörtern und ihrer Anzahl
In diesem Schritt erstellen wir ein Objekt, bei dem der Schlüssel das Wort und der Wert seine Anzahl im Array ist. Die Logik dafür ist ziemlich einfach. Wir erstellen ein leeres Objekt keywords und prüfen, ob das Wort bereits darin vorhanden ist. Wenn ja, erhöhen wir den Wert um eins, wenn nicht, erstellen wir ein neues Schlüssel-Wert-Paar. Hier ist, wie es aussieht
// Step 2) forming an object with keywords and their count
var keywords = {};
for (var i = 0; i < nonStopWords.length; i++) {
// checking if the word(property) already exists
// if it does increment the count otherwise set it to one
if (nonStopWords[i] in keywords) {
keywords[nonStopWords[i]] += 1;
} else {
keywords[nonStopWords[i]] = 1;
}
}
Schritt 3) Sortieren des Objekts durch Umwandlung in ein 2D-Array
In diesem Schritt wandeln wir zuerst das obige Objekt in ein 2D-Array um, damit wir die native sort-Methode von JavaScript verwenden können, um es zu sortieren
// Step 3) sorting the object by first converting it to a 2D array
var sortedKeywords = [];
for (var keyword in keywords) {
sortedKeywords.push([keyword, keywords[keyword]])
}
sortedKeywords.sort(function(a, b) {
return b[1] - a[1]
});
Schritt 4) Anzeigen der Top 4 Schlüsselwörter und ihrer Anzahl
Das Ergebnis des obigen Schritts war ein 2D-Array namens sortedKeywords. In diesem Schritt zeigen wir die ersten vier (oder wenige, wenn die Gesamtzahl der Wörter weniger als 4 beträgt) Elemente dieses Arrays an. Bei jedem Element befindet sich das Wort an Position 0 und seine Anzahl an Position 1.
Wir erstellen für jeden Eintrag ein neues Listenelement und hängen es an das ul an, das von topKeywords repräsentiert wird
// Step 4) displaying top 4 keywords and their count
for (var i = 0; i < sortedKeywords.length && i < 4; i++) {
var li = document.createElement('li');
li.innerHTML = "" + sortedKeywords[i][0] + ": " + sortedKeywords[i][1];
topKeywords.appendChild(li);
}
Kommen wir nun zur Ermittlung des Lesbarkeits-Scores.
Teil 3: Ermitteln des Lesbarkeits-Scores
Um Ihre Botschaft in einem Text zu vermitteln, möchten Sie Wörter verwenden, die Ihre Zielgruppe verstehen kann. Andernfalls ist es sinnlos zu schreiben. Aber wie kann man messen, wie schwierig es ist, einen Text zu verstehen?
Hier kommt der Lesbarkeits-Score.
Leute, die intelligenter sind als wir, haben viele Skalen entwickelt, um den Schwierigkeitsgrad eines Lesetextes zu messen. Für unsere App verwenden wir den Flesch-Lesbarkeits-Test, der einer der am häufigsten verwendeten Tests für diesen Zweck ist. Das ist der, auf den Microsoft Word setzt!
Beim Flesch-Lesbarkeits-Test reichen die Punktzahlen von null bis hundert. Höhere Punktzahlen deuten auf Material hin, das leichter zu lesen ist; niedrigere Zahlen kennzeichnen Abschnitte, die schwieriger zu lesen sind. Er basiert auf einer etwas komplexen mathematischen Formel, über die wir uns keine Gedanken machen müssen, denn im Web gibt es für (fast) alles eine API.
Obwohl es viele kostenpflichtige Optionen zur Berechnung von Lesbarkeits-Scores gibt, werden wir die Readability Metrics API von Mashape verwenden, die absolut kostenlos ist. Sie bietet auch einige andere Lesbarkeits-Scores, falls Sie interessiert sind.
Um die API zu nutzen, müssen wir eine POST-Anfrage an eine bestimmte URL senden, die den zu bewertenden Text enthält. Das Gute an Mashape ist, dass es Ihnen erlaubt, seine APIs direkt aus dem Browser zu nutzen.
Ich werde reines JavaScript verwenden, um diesen Ajax-Aufruf zu tätigen. Wenn Sie vorhaben, jQuery zu verwenden, finden Sie diese Dokumentationsseite nützlich, oder wenn Sie eine serverseitige Sprache verwenden möchten, beziehen Sie sich bitte auf die API-Homepage für Codebeispiele.
So sieht der Code für die Anforderung aus
// readability level using readability-metrics API from Mashape
readability.addEventListener('click', function() {
// placeholder until the API returns the score
readability.innerHTML = "Fetching score...";
var requestUrl = "https://ipeirotis-readability-metrics.p.mashape.com/getReadabilityMetrics?text=";
var data = input.value;
var request = new XMLHttpRequest();
request.open('POST', encodeURI(requestUrl + data), true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.setRequestHeader("X-Mashape-Authorization", "Your API key | Don't use mine!");
request.send();
request.onload = function() {
if (this.status >= 200 && this.status < 400) {
// Success!
readability.innerHTML = readingEase(JSON.parse(this.response).FLESCH_READING);
} else {
// We reached our target server, but it returned an error
readability.innerHTML = "Not available.";
}
};
request.onerror = function() {
// There was a connection error of some sort
readability.innerHTML = "Not available.";
};
});
Der größte Teil des obigen Codes besteht aus einem Standard-Ajax-Aufruf, aber hier sind drei wichtige Punkte zu beachten:
- Um diese API zu nutzen, benötigen Sie ein kostenloses Mashape-Konto. Sobald Sie eines haben, erhalten Sie einen Schlüssel, den Sie in den Autorisierungs-Header einfügen können.
- Die API gibt viele verschiedene Scores zurück, und derjenige, den wir brauchen, befindet sich in der
FLESCH_READING-Eigenschaft der Antwort. - Die Antwort enthält eine Zahl zwischen 0 und 100, die allein nichts für einen Benutzer aussagt. Wir müssen sie also in ein sinnvolles Format umwandeln, und das leistet die Funktion
readingEase. Sie nimmt diese Zahl als Eingabe und gibt einen String aus, basierend auf dieser Wikipedia-Tabelle.
function readingEase(num) {
switch (true) {
case (num <= 30):
return "Readability: College graduate.";
break;
case (num > 30 && num <= 50):
return "Readability: College level.";
break;
// more cases
default:
return "Not available.";
break;
}
}
Das war's! Das war die gesamte Logik, die in die Erstellung einer Wortzähl-App einfließt. Ich habe nicht jedes kleine Detail erklärt, weil Sie das selbst herausfinden können, indem Sie sich den Code ansehen. Wenn Sie irgendwo stecken bleiben, schauen Sie sich gerne den vollständigen Quellcode auf GitHub an.
Weiterentwicklung
Obwohl die App gut aussieht und großartig funktioniert, gibt es ein paar Möglichkeiten, sie zu verbessern, wie zum Beispiel:
- Behandlung von Punkten: Aktuell zählt unsere App, wenn Sie eine E-Mail wie
[email protected]eingeben, diese als zwei verschiedene Sätze. Gleiches gilt, wenn Sie einen Domainnamen oder Wörter wie „vs.“, „z. B.“ usw. eingeben. Eine Möglichkeit, damit umzugehen, ist die Verwendung einer manuellen Liste und das Herausfiltern mittels Regex. Da jedoch keine solche Liste sofort verfügbar ist, müssen wir sie manuell kuratieren. Lassen Sie mich bitte in den Kommentaren wissen, wenn Sie eine bessere Methode kennen. - Unterstützung für mehr Sprachen: Derzeit behandelt unsere App alle Fälle der englischen Sprache sehr gut. Aber was ist, wenn Sie sie für Deutsch verwenden möchten? Nun, Sie müssten die Stoppwörter des Deutschen einfügen. Das ist alles. Der Rest bleibt gleich. Am besten wäre es, eine Sprachauswahl über ein Dropdown-Menü zu haben, und die App sollte entsprechend funktionieren.
Ich hoffe, Sie hatten Spaß daran, diesem Tutorial zu folgen. Hinterlassen Sie gerne einen Kommentar unten, wenn Sie Fragen haben. Oder um einfach Hallo zu sagen! Ich helfe immer gerne.
Aus reiner Neugier, wie würden Sie verhindern, dass „Mr. Brooks ist nicht im Büro.“ als zwei Sätze gezählt wird?
Entschuldigung. Ich habe den Rest gelesen. Sie erklären es am Ende! Toller Beitrag übrigens!
Wortzählung fehlgeschlagen. Wenn der String „foo ä bar“ ist, gibt es 3 Wörter, aber aufgrund der verwendeten Wortgrenze zeigt die App nur 2 Wörter an. Dies kann durch die Verwendung eines
u-Flags im Regex oder durch den Wechsel zu einer anderen Wortzähllogik behoben werden.Oh. Es gibt einen Absatz dazu… Entschuldigung.
Schöner Artikel!
Ein Randfall
Das Einfügen großer Inhalte über das Kontextmenü der rechten Maustaste wird hier nicht behandelt. Es sollte jedoch nicht schwer hinzuzufügen sein.
Leistungsverbesserung
Das Ausführen solch großer Arbeiten im Rahmen der keyup-Ereignisbehandlung ist möglicherweise keine gute Idee. Vielleicht könnten wir hier Debouncing verwenden. https://css-tricks.de/debouncing-throttling-explained-examples/
Ich würde das
input-Ereignis und Debouncing verwenden.Um in einem Satz College-Absolventen-Leseniveau zu erreichen.
„Ich stelle fest, dass Ambidextrie die Verhandlungen mit dem Parlament erheblich erleichtert.“
Ich denke, die Beispiele könnten durch die Verwendung von Array-Methoden anstelle von Schleifen verbessert werden, zum Beispiel
und
und
Diese Art von Code ist klarer und selbsterklärender – es ist offensichtlicher eine Reihe von Transformationen/Operationen auf dem Text. Außerdem vermeidet es das visuelle Rauschen von
for-Schleifen.Dem stimme ich zu. Viel idiomatischeres JS.
Ähnlich wie bei einem Wörterbuch mit Stoppwörtern sollten Sie ein Wörterbuch mit Abkürzungen verwenden, um sie von Punkten am Satzende zu unterscheiden. Punkte in Domainnamen, Benutzernamen usw. können leicht erfasst werden, da nach ihnen kein Leerzeichen folgt.
Es gibt einen kleinen Fehler im Regex zum Finden von Wörtern
/\b[-?(\w+)?]+\b/gi. Es sollte(anstelle von[sein.Das aktuelle Regex stimmt mit Wörtern überein, die beliebige Zeichen (
[]) unter diesen Zeichen-?(\w+)?ein- oder mehrmals+enthalten (\wbedeutet beliebige Wortzeichen, wie Sie sagten). Das bedeutet, dasshello+(-world?)als ein Wort erkannt wird.Die in diesem Artikel verwendeten RegExps sind etwas „seltsam“.
Zum Beispiel zählt die Verwendung von
/[.|!|?]/gzum Teilen auch das|-Zeichen.Wenn Sie Gruppierung mit eckigen Klammern verwenden, müssen Sie nicht
|verwenden, da jedes Zeichen darin als solches gezählt wird, einschließlich Klammern, Punkten oder|. Die Verwendung vongzum Aufteilen eines Strings ist ebenfalls falsch, da split bereits alle Vorkommen dieses Regex im String findet.Jetzt sprechen wir über
value.match(/\b[-?(\w+)?]+\b/gi);.Wieder scheint der Autor keine Gruppen zu verstehen. ‚non-?sense‘ wird berücksichtigt, aber es ist nicht die Absicht des Autors.
/\b[-\w]+\b/gist im Grunde alles, was der Autor braucht, um die beabsichtigten Ergebnisse zu erzielen.Das
i(ignoreCase-Flag) ist ebenfalls nutzlos, da\walle Zeichen einschließt, nicht nur Groß- oder Kleinbuchstaben.Es gibt andere Fallstricke, die nicht so toll sind, besonders wenn es um nicht-lateinische Alphabete geht, aber es ist ein anständiger Ausgangspunkt für einen englischen Zähler, also… Ich habe die Anstrengung geschätzt, aber ich denke auch, Sie sollten vor der Veröffentlichung technische Überprüfungen anfordern.
Dies erhöht die Wahrscheinlichkeit, dass die Qualität des Inhalts sehr hoch ist, wie es bereits für die meisten hier vorhandenen Inhalte der Fall ist.
Mit freundlichen Grüßen
Ich erinnere mich, dass es Anfang der 1990er Jahre ein Programm gab, das alle Wörter und wie oft jedes Wort in einem Text vorkam, zählte. Aber jetzt weiß ich nichts mehr über dieses Programm oder diese App. Es hieß damals WORD Count oder WORD. Wenn Sie von diesem Programm / dieser App wissen, lassen Sie es mich bitte wissen.
Mein Problem ist, wie man das Vorkommen verschiedener Wörter in einem Dokument / Artikel zählt.