Comment puis-je traiter chaque lettre de texte en utilisant Javascript?

363

Je voudrais alerter chaque lettre individuelle d'une chaîne, mais je ne sais pas comment procéder.

Donc, si j'ai:

var str = 'This is my string';

Je voudrais pouvoir alerter séparément T, h, i, s, etc. Ce n'est que le début d'une idée sur laquelle je travaille, mais j'ai besoin de savoir comment traiter chaque lettre séparément.

Je veux utiliser jQuery et pensais que je pourrais avoir besoin d'utiliser la fonction split après avoir testé la longueur de la chaîne.

Des idées?

Nic Hubbard
la source
3
Peut-être que vous le cherchiez: à partir d'ES6, il y en a for(const c of str) { ... }. Plus de cela plus loin dans une réponse assez détaillée mais pas suffisamment votée. PS: Le lien @ ARJUN ne fonctionne pas pour moi.
Max

Réponses:

421

Si l'ordre des alertes est important, utilisez ceci:

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

Si l'ordre des alertes n'a pas d'importance, utilisez ceci:

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

Eli Gray
la source
2
utiliser le []pour obtenir le caractère dans une position spécifique n'est pas pris en charge dans IE <9
vsync
13
comme indiqué dans l'autre réponse, vous pouvez utiliser str.charAt (i) à la place des []. pour en savoir plus sur les raisons pour lesquelles vous devriez utiliser charAt vs [], voir string.charAt (x) ou string [x]
Julian Soro
12
J'ai du mal à croire qu'un compilateur JS moderne recalcule la longueur si la chaîne n'a pas été modifiée à l'intérieur de la boucle. Dans toutes les autres langues, je ferais avec plaisir la vérification de la longueur dans la clause de test de la boucle for, en supposant que le compilateur connaît le mieux et l'optimiserait en conséquence.
Echelon
3
@Dagmar: Javascript n'utilise pas UTF-8, il utilise UTF-16 (ou UCS-2, selon le navigateur). Chaque caractère peut être représenté comme UTF-8 ou UTF-16 mais ne pas avoir ce problème. Les seuls qui ont le problème sont ceux qui nécessitent quatre octets en UTF-16 plutôt que deux octets. 💩 est un caractère qui nécessite quatre octets en UTF-16. Les termes clés pour rechercher plus d'informations sont "plan astral", "non-BMP" et "paire de substitution".
hippietrail
1
@Dagmar: Java et Javascript ont tous deux en commun UTF-16 (anciennement UCS-). La troisième plate-forme majeure qui l'utilise est Windows. Les protocoles Unix, MacOS et Internet utilisent UTF-8. charAtest resté des jours UCS-2 où il n'y avait pas de paires de substitution et pour résoudre le problème, une nouvelle fonction a codepointAtété ajoutée à JavaScript qui gère correctement notre pile de caca amicale. Je crois que Java l'a aussi.
hippietrail
240

C'est probablement plus que résolu. Je veux juste contribuer avec une autre solution simple:

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);
});
M. Goferito
la source
4
le dernier exemple peut être simplement[...text].forEach(console.log)
Govind Rai
10
Non, ça ne peut pas. forEach()transmet l'index et le tableau comme deuxième et troisième argument. Je préfère ne pas enregistrer cela ..
M. Goferito
1
Notez que l'opérateur de propagation (premier exemple) et l'appel fractionné (dernier exemple) créeront un nouveau tableau. Cela ne sera généralement pas un problème, mais pourrait être coûteux pour les grandes chaînes ou les utilisations fréquentes.
Randolpho
Qu'en est-ilfor (let c of [...text]) { console.log(c) }
Flimm
Avec cela, vous créez un nouveau tableau à partir de la chaîne. Je ne vois pas l'avantage. let c of textfait déjà le travail.
M. Goferito
73

Une solution possible en javascript pur:

for (var x = 0; x < str.length; x++)
{
    var c = str.charAt(x);
    alert(c);
}
miku
la source
Ce serait probablement mieux avec var x = 0 et var c = str.charAt (x).
Rich
2
De plus, str.length doit être stocké dans une variable afin de ne pas avoir à continuer d'être consulté.
Eli Gray
8
@EliGrey Est-il vraiment si important de mettre la longueur dans une variable? Avez-vous des repères lorsque cela serait préférable à moins de lignes de code?
pm_labs
@paul_sns Fait intéressant, il semble y avoir une différence mineure , au moins dans Edge (différence de 0,7 ms pour un tableau d'éléments de 10000): jsfiddle.net/carcigenicate/v8vvjoc1/1 . Probablement pas un test parfait, mais il est basé sur une moyenne de 10000 tests.
Carcigenicate
1
@paul_sns Aussi intéressant, Chrome a fait le même test dans environ 2% du temps (~ 5 ms contre ~ 0,0997 ms), et les deux versions ont donné le même temps, il semble donc que Edge ne soit pas optimisé.
Carcigenicate
69

Comment traiter chaque lettre de texte (avec des repères)

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

pour

Classique et de loin celui avec le plus de performances . Vous devriez aller avec celui-ci si vous prévoyez de l'utiliser dans un algorithme critique de performance, ou qu'il nécessite la compatibilité maximale avec les versions du navigateur.

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

pour ... de

for ... of est le nouveau ES6 pour itérateur. Pris en charge par la plupart des navigateurs modernes. Il est visuellement plus attrayant et moins sujet aux erreurs de frappe. Si vous optez pour celui-ci dans une application de production, vous devriez probablement utiliser un transpilateur comme Babel .

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

pour chaque

Approche fonctionnelle . Approuvé Airbnb . Le plus gros inconvénient de le faire de cette façon est le split(), qui crée un nouveau tableau pour stocker chaque lettre individuelle de la chaîne.

Pourquoi? Cela renforce notre règle immuable. Il est plus facile de raisonner sur les fonctions pures qui renvoient des valeurs que sur les effets secondaires.

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

ou

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

Ce qui suit sont ceux que je n'aime pas.

pour ... dans

Contrairement à pour ... de, vous obtenez l'index des lettres au lieu de la lettre. Il fonctionne assez mal.

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

carte

Approche fonctionnelle, ce qui est bien. Cependant, la carte n'est pas destinée à être utilisée pour cela. Il doit être utilisé lorsque vous devez modifier les valeurs à l'intérieur d'un tableau, ce qui n'est pas le cas.

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

ou

let result = '';
str.split('').map(function(letter) {
  result += letter;
});
zurfyx
la source
1
Sur ma machine, la forboucle classique était en fait la deuxième plus lente, alors qu'elle for...ofétait la plus rapide (environ trois fois plus rapide que for).
John Montgomery
1
Où est la référence? Quelle est la solution la plus rapide?
poitroae
1
@johnywhy C'était il y a deux ans et le lien est mort, donc je ne sais pas comment vous vous attendez à ce que je défende le résultat que j'ai obtenu à l'époque. La mise en place d'un nouveau benchmark est désormais conforme à la conclusion de zurfyx, la forboucle étant légèrement plus rapide.
John Montgomery
1
@JohnMontgomery Je ne m'attends pas à ce que vous fassiez quoi que ce soit. Juste une note aux futurs lecteurs que vos résultats sont différents de la réponse. Personnellement, j'aimerais savoir quels résultats s'appliquent aux navigateurs aujourd'hui 2020, même si 2018 n'était pas si lointain. Quel lien est mort?
johny pourquoi
1
@johnywhy Le lien en haut avec tous les tests réels me renvoie un 404.
John Montgomery
42

La plupart des réponses, sinon toutes, sont erronées car elles se brisent chaque fois qu'il y a un caractère dans la chaîne en dehors du BMP Unicode (plan multilingue de base) . Cela signifie que tous les Emoji seront brisés .

JavaScript utilise UTF- 16 Unicode pour toutes les chaînes. Dans UTF-16, les caractères au-delà du BMP sont constitués de deux parties, appelées « paire de substitution » et la plupart des réponses ici traiteront chaque partie de ces paires individuellement au lieu d'un seul caractère.

Une façon dans le JavaScript moderne depuis au moins 2016 est d'utiliser le nouvel itérateur String . Voici l'exemple (presque) tout droit sorti de 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
la source
4
Pour une solution moderne pour diviser une chaîne en caractères tout en tenant compte des paires de substitution, voir: stackoverflow.com/a/42596897/527702
hippietrail
20

Vous pouvez essayer ceci

var arrValues = 'This is my string'.split('');
// Loop over each value in the array.
$.each(arrValues, function (intIndex, objValue) {
    alert(objValue);
})
Adriaan Stander
la source
11
Est toujours une option, mais pas performante. Ne mettez pas jQuery partout.
cagatay
10

Encore une solution ...

var strg= 'This is my string';
for(indx in strg){
  alert(strg[indx]);
}
Pamsix
la source
3
Si vous ne voulez que le caractère et non l'index, il serait plus rapide d'utiliser une for..ofbouclefor (let ch of t) { alert(ch) }
Shaheen Ghiassy
10

Quand j'ai besoin d'écrire du code court ou un one-liner, j'utilise ce "hack":

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

Cela ne comptera pas les nouvelles lignes, ce qui peut être une bonne ou une mauvaise chose. Si vous souhaitez inclure des sauts de ligne, remplacez: /./par /[\S\s]/. Les autres monolignes que vous verrez probablement utiliser, .split()ce qui pose de nombreux problèmes

Downgoat
la source
meilleure réponse. Prend en compte les problèmes avec unicode et peut également être utilisé avec des constructions fonctionnelles avec .map () etc.
rofrol
La seule chose que je n'aime pas dans celui-ci, c'est quand je veux accéder aux paramètres supplémentaires passés à la forEachfonction de l' appel par rapport aux paramètres envoyésreplace . Si je sais que je suis en ASCII, je pense que j'ai encore des cas d'utilisation pour split. Excellente réponse, cependant!
ruffin
Cette réponse a le bonus de présélectionner les valeurs contre
lesquelles
1
Je pensais que cela ne prendrait pas en compte les problèmes Unicode à moins d'avoir le udrapeau avec le gdrapeau? OK vient de tester et j'avais raison.
hippietrail
9

Le nouveau JS permet ceci:

const str = 'This is my string';
Array.from(str).forEach(alert);
papajson
la source
8

Il est préférable d'utiliser l'instruction for ... of, si la chaîne contient des caractères unicode, en raison de la taille d'octet différente.

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

réponse courte: Array.from(string)vous donnera ce que vous voulez probablement et vous pourrez ensuite le répéter ou quoi que ce soit, car il ne s'agit que d'un tableau.

ok essayons-le avec cette chaîne: abc|⚫️\n⚪️|👨‍👩‍👧‍👧 .

les points de code sont:

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

certains caractères ont donc un point de code (octet) et certains en ont deux ou plus, et une nouvelle ligne a été ajoutée pour des tests supplémentaires.

donc après le test, il y a deux façons:

  • octet par octet (point de code par point de code)
  • groupes de caractères (mais pas les emoji de toute la famille)

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
la source
7

Vous pouvez désormais parcourir les points de code Unicode individuels contenus dans une chaîne à l'aide de String.prototype[@@iterator], qui renvoie une valeur de type Symbol bien connu Symbol.iterator- l'itérateur par défaut pour les objets de type tableau ( Stringdans ce cas).

Exemple de code:

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.

Cela fonctionne avec les caractères Unicode tels que les emoji ou les caractères non romains qui déclencheraient les constructions héritées.

Référence: Lien MDN vers String.prototype @@ itérateur .

Aditya MP
la source
2
Notez que vous pouvez le faire de manière plus courte avec une for ... ofboucle également sur la chaîne - c'est-à-dire le sucre de syntaxe pour accéder à l'itérateur.
Aditya MP
6

Vous pouvez maintenant utiliser dans mot-clé.

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

mih0vil
la source
L'usage est une mauvaise pratique et horrible lorsqu'il n'est pas filtré, je le déconseille vivement
Downgoat
4
@Downgoat pourquoi? Quel est le problème? Je veux dire si je suis dans une situation où je sais que 'in' est supporté par mon moteur Javascript, et que mon code ne trouvera pas sa place dans un autre moteur ... pourquoi ne pas l'utiliser?
TKoL
@TKoL Voir ceci .
Alan
@Alan inest une partie légitime de la langue. Utilisez les choses de manière appropriée. Votre article met en garde que inles touches alpha sont interprétées de la même manière que les touches numériques. Donc? C'est peut-être ce que tu veux. On pourrait également dire que d'autres méthodes ignorent incorrectement les clés alpha. Imo, ofa un comportement correct. Dans les tableaux JS, les éléments sans clé alpha ont toujours des clés: numériques. Dans ma console, JS traite "correctement" la touche alpha comme les touches numériques:>const arr = ['a', 'b'] >arr.test = 'hello' >arr 0: "a" 1: "b" test: "hello" length: 2
johny pourquoi
5

Vous pouvez obtenir un tableau des caractères individuels comme ça

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

puis boucle en utilisant Javascript ordinaire, ou bien vous pouvez parcourir les caractères de la chaîne en utilisant jQuery par

var test = "test string";

$(test.split('')).each(function (index,character) {
    alert(character);
});
Riches
la source
5

vous pouvez convertir cette chaîne en un tableau de caractères en utilisant split(), puis l'itérer.

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

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

Muhammed Moussa
la source
apparemment, cela échoue avec les caractères unicode et les symboles graphiques.
johny pourquoi
4

Si vous souhaitez effectuer une transformation sur le texte au niveau d'un caractère et récupérer le texte transformé à la fin, vous feriez quelque chose comme ceci:

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

Donc, les étapes:

  • Fractionner la chaîne en un tableau (liste) de caractères
  • Mappez chaque personnage via un foncteur
  • Joignez le tableau résultant de caractères ensemble dans la chaîne résultante
Vajk Hermecz
la source
0

Dans le JavaScript d'aujourd'hui, vous pouvez

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

De toute évidence, c + c représente tout ce que vous voulez faire avec c.

Cela revient

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

Pum Walters
la source
Peut-être:[...'This is my string'].map((c)=>c+c)
Alan
0

Cela devrait fonctionner dans les anciens navigateurs et avec des caractères UTF-16 comme 💩.

Cela devrait être la solution la plus compatible. Cependant, elle est moins performante qu'une forboucle.

J'ai généré l'expression régulière en utilisant regexpu

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

J'espère que cela t'aides!

Ben Gubler
la source
Qu'entendez-vous par «moins performant»? Je pense que vous voulez dire "plus lent" car il est plus conforme à l'exigence et il fonctionne bien.
hippietrail
-1

Vous pouvez accéder à des caractères uniques avec str.charAt(index)ou str[index]. Mais cette dernière méthode ne fait pas partie d'ECMAScript, il vaut donc mieux choisir l'ancienne.

Gombo
la source
Je resterais loin de ça. Malheureusement, cela ne fonctionne pas dans toutes les versions d'IE. Croyez-moi. Je l'ai appris à la dure.
Xavi
3
Il fait partie d'ECMAScript, mais uniquement dans la 5e édition nouvellement publiée, pas la 3e.
kangax
-1

Si vous souhaitez animer chaque personnage, vous devrez peut-être l'envelopper dans l'élément span;

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

Je pense que c'est la meilleure façon de le faire, puis de traiter les portées. (par exemple avec TweenMax)

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

Chris Panayotoff
la source
-1

Essayez ce 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>
Miaou
la source