Comment obtenir une chaîne dans un tableau de caractères en JavaScript?

371

Comment convertir une chaîne en un tableau de caractères en JavaScript?

Je pense obtenir une chaîne comme "Hello world!"dans le tableau
['H','e','l','l','o',' ','w','o','r','l','d','!']

DarkLightA
la source

Réponses:

494

Remarque: ce n'est pas compatible Unicode. "I💖U".split('')résulte dans le tableau de 4 caractères ["I", "�", "�", "u"]qui peut conduire à des bugs dangereux. Voir les réponses ci-dessous pour des alternatives sûres.

Il suffit de le diviser par une chaîne vide.

var output = "Hello world!".split('');
console.log(output);

Voir les String.prototype.split()documents MDN .

meder omuraliev
la source
31
Cela ne prend pas en compte les paires de substitution. "𨭎".split('')résulte en ["�", "�"].
hippietrail
59
Voir la réponse de @ hakatashi ailleurs dans ce fil. J'espère que tout le monde voit ça ... N'UTILISEZ PAS CETTE MÉTHODE, CE N'EST PAS
SÉCURISÉ
3
Un peu tard pour la fête. Mais pourquoi voudrait-on jamais faire un tableau d'une chaîne? Une chaîne est déjà un tableau ou je me trompe? "randomstring".length; //12 "randomstring"[2]; //"n"
Luigi van der Pal
4
@LuigivanderPal Une chaîne n'est pas un tableau, mais elle est très similaire. Cependant, il n'est pas similaire à un tableau de caractères. Une chaîne est similaire à un tableau de nombres de 16 bits, dont certains représentent des caractères et certains représentent la moitié d'une paire de substitution. Par exemple, str.lengthne vous indique pas le nombre de caractères dans la chaîne, car certains caractères prennent plus d'espace que d'autres; str.lengthvous indique le nombre de nombres 16 bits.
Theodore Norvell du
291

Comme hippie trail suggère , la réponse de Meder peut briser les paires de substitution et mal interpréter « caractères. » Par exemple:

// DO NOT USE THIS!
> '𝟘𝟙𝟚𝟛'.split('')
[ '�', '�', '�', '�', '�', '�', '�', '�' ]

Je suggère d'utiliser l'une des fonctionnalités ES2015 suivantes pour gérer correctement ces séquences de caractères.

Spread syntax ( déjà répondu par insertusernamehere)

> [...'𝟘𝟙𝟚𝟛']
[ '𝟘', '𝟙', '𝟚', '𝟛' ]

Array.from

> Array.from('𝟘𝟙𝟚𝟛')
[ '𝟘', '𝟙', '𝟚', '𝟛' ]

uDrapeau RegExp

> '𝟘𝟙𝟚𝟛'.split(/(?=[\s\S])/u)
[ '𝟘', '𝟙', '𝟚', '𝟛' ]

Utilisez /(?=[\s\S])/uau lieu de /(?=.)/ucar .ne correspond pas aux sauts de ligne .

Si vous êtes encore à l'ère ES5.1 (ou si votre navigateur ne gère pas correctement cette expression régulière - comme Edge), vous pouvez utiliser cette alternative (transposée par Babel ):

> '𝟘𝟙𝟚𝟛'.split(/(?=(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/);
[ '𝟘', '𝟙', '𝟚', '𝟛' ]

Notez que Babel essaie également de gérer correctement les substituts inégalés. Cependant, cela ne semble pas fonctionner pour les substituts bas inégalés.

Testez tout dans votre navigateur:

hakatashi
la source
Comment avez-vous formé ces personnages? Il semble que chaque caractère mesure 4 octets.
user420667
2
@ user420667 les caractères proviennent d'un plan de caractères supplémentaire (dans la table unicode) avec de "gros" points de code donc ils ne tiennent pas sur 16 octets. L'encodage utf-16 utilisé en javascript présente ces caractères comme des paires de substitution (caractères spéciaux qui ne sont utilisés que comme paires pour former d'autres caractères à partir d'avions supplémentaires). Seuls les caractères du plan de caractères principal sont présentés avec 16 octets. Les caractères spéciaux de la paire de substitution proviennent également du plan du personnage principal, si cela fait sens.
Olga
1
Performances des différentes techniques , spread op ressemble au champion (chrome 58).
Adrien
4
Notez que cette solution divise certains emoji tels que 🏳️‍🌈, et divise la combinaison de signes diacritiques et de caractères. Si vous souhaitez diviser en grappes de graphèmes au lieu de caractères, voir stackoverflow.com/a/45238376 .
user202729
3
Notez que bien que ne pas séparer les paires de substitution soit génial, ce n'est pas une solution polyvalente pour garder les "caractères" (ou plus précisément, les graphèmes ) ensemble. Un graphème peut être composé de plusieurs points de code; par exemple, le nom de la langue Devanagari est "देवनागरी", qui est lu par un locuteur natif comme cinq graphèmes, mais prend huit points de code pour produire ...
TJ Crowder
71

La spreadsyntaxe

Vous pouvez utiliser la syntaxe répartie , un initialiseur de tableau introduit dans la norme ECMAScript 2015 (ES6) :

var arr = [...str];

Exemples

function a() {
    return arguments;
}

var str = 'Hello World';

var arr1 = [...str],
    arr2 = [...'Hello World'],
    arr3 = new Array(...str),
    arr4 = a(...str);

console.log(arr1, arr2, arr3, arr4);

Les trois premiers résultats:

["H", "e", "l", "l", "o", " ", "W", "o", "r", "l", "d"]

Le dernier se traduit par

{0: "H", 1: "e", 2: "l", 3: "l", 4: "o", 5: " ", 6: "W", 7: "o", 8: "r", 9: "l", 10: "d"}

Prise en charge du navigateur

Vérifiez le tableau de compatibilité ECMAScript ES6 .


Lectures complémentaires

spreadest également référencé comme " splat" (par exemple en PHP ou Ruby ou " scatter" (par exemple en Python ).


Démo

Essayez avant d'acheter

insertusernamehere
la source
1
Si vous utilisez l'opérateur d'étalement en combinaison avec un compilateur vers ES5, cela ne fonctionnera pas dans IE. Prenez cela en considération. Cela m'a pris des heures pour comprendre quel était le problème.
Stef van den Berg
14

Vous pouvez également utiliser Array.from.

var m = "Hello world!";
console.log(Array.from(m))

Cette méthode a été introduite dans ES6.

Référence

Array.from

Rajesh
la source
10

C'est une vieille question mais je suis tombé sur une autre solution non encore listée.

Vous pouvez utiliser la fonction Object.assign pour obtenir la sortie souhaitée:

var output = Object.assign([], "Hello, world!");
console.log(output);
    // [ 'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!' ]

Pas nécessairement vrai ou faux, juste une autre option.

Object.assign est bien décrit sur le site MDN.

David Thomas
la source
2
C'est un long chemin à parcourir Array.from("Hello, world").
TJ Crowder
@TJCrowder C'est un long chemin à [..."Hello, world"]
parcourir
@chharvey - Heh. :-)
TJ Crowder
9

C'est déjà:

var mystring = 'foobar';
console.log(mystring[0]); // Outputs 'f'
console.log(mystring[3]); // Outputs 'b'

Ou pour une version plus ancienne compatible avec les navigateurs, utilisez:

var mystring = 'foobar';
console.log(mystring.charAt(3)); // Outputs 'b'

dansimau
la source
4
-1: ce n'est pas le cas. Essayez-le:alert("Hello world!" == ['H','e','l','l','o',' ','w','o','r','l','d'])
R. Martinho Fernandes
5
Désolé. Je suppose que ce que je voulais dire est: "vous pouvez accéder à des caractères individuels par référence d'index comme celui-ci sans créer un tableau de caractères".
dansimau
3
Pas cross-browser fiable, vous ne pouvez pas. Il s'agit d'une fonctionnalité ECMAScript Fifth Edition.
bobince
8
La version multi-navigateur est mystring.charAt(index).
2010
1
+1 pour - charAt()bien que je préfère utiliser la variante array-ish. Darn IE.
Zenexer
4

Il y a (au moins) trois choses différentes que vous pourriez concevoir comme un "personnage", et par conséquent, trois catégories différentes d'approche que vous pourriez vouloir utiliser.

Division en unités de code UTF-16

Les chaînes JavaScript ont été à l'origine inventées en tant que séquences d'unités de code UTF-16, à un moment de l'histoire où il y avait une relation un à un entre les unités de code UTF-16 et les points de code Unicode. La .lengthpropriété d'une chaîne mesure sa longueur en unités de code UTF-16, et lorsque vous le faites, someString[i]vous obtenez la i ème unité de code UTF-16 de someString.

Par conséquent, vous pouvez obtenir un tableau d'unités de code UTF-16 à partir d'une chaîne en utilisant une boucle for de style C avec une variable d'index ...

const yourString = 'Hello, World!';
const charArray = [];
for (let i=0; i<=yourString.length; i++) {
    charArray.push(yourString[i]);
}
console.log(charArray);

Il existe également plusieurs méthodes rapides pour réaliser la même chose, comme l'utilisation .split()de la chaîne vide comme séparateur:

const charArray = 'Hello, World!'.split('');
console.log(charArray);

Cependant, si votre chaîne contient des points de code composés de plusieurs unités de code UTF-16, cela les divisera en unités de code individuelles, ce qui peut ne pas être ce que vous voulez. Par exemple, la chaîne '𝟘𝟙𝟚𝟛'est composée de quatre points de code Unicode (points de code 0x1D7D8 à 0x1D7DB) qui, en UTF-16, sont chacun constitués de deux unités de code UTF-16. Si nous divisons cette chaîne en utilisant les méthodes ci-dessus, nous obtiendrons un tableau de huit unités de code:

const yourString = '𝟘𝟙𝟚𝟛';
console.log('First code unit:', yourString[0]);
const charArray = yourString.split('');
console.log('charArray:', charArray);

Division en points de code Unicode

Donc, peut-être que nous voulons plutôt diviser notre chaîne en points de code Unicode! Cela a été possible depuis que ECMAScript 2015 a ajouté le concept d'un itérable au langage. Les chaînes sont désormais itérables, et lorsque vous les parcourez (par exemple avec une for...ofboucle), vous obtenez des points de code Unicode, pas des unités de code UTF-16:

const yourString = '𝟘𝟙𝟚𝟛';
const charArray = [];
for (const char of yourString) {
  charArray.push(char);
}
console.log(charArray);

Nous pouvons raccourcir cela en utilisant Array.from, qui itère sur l'itérable qu'il est passé implicitement:

const yourString = '𝟘𝟙𝟚𝟛';
const charArray = Array.from(yourString);
console.log(charArray);

Cependant, les points de code unicode ne sont pas la plus grande chose qui pourrait peut - être considéré comme un « caractère » soit . Voici quelques exemples de choses qui pourraient raisonnablement être considérées comme un seul "caractère", mais être constituées de plusieurs points de code:

  • Caractères accentués, si l'accent est appliqué avec un point de code de combinaison
  • Drapeaux
  • Quelques emojis

Nous pouvons voir ci-dessous que si nous essayons de convertir une chaîne avec de tels caractères en un tableau via le mécanisme d'itération ci-dessus, les caractères finissent par être décomposés dans le tableau résultant. (Si aucun des caractères ne s'affiche sur votre système, yourStringci - dessous se compose d'un A majuscule avec un accent aigu, suivi du drapeau du Royaume-Uni, suivi d'une femme noire.)

const yourString = 'Á🇬🇧👩🏿';
const charArray = Array.from(yourString);
console.log(charArray);

Si nous voulons conserver chacun de ces éléments comme un seul élément dans notre tableau final, nous avons besoin d'un tableau de graphèmes , pas de points de code.

Division en graphèmes

JavaScript n'a pas de support intégré pour cela - du moins pas encore. Nous avons donc besoin d'une bibliothèque qui comprend et implémente les règles Unicode pour quelle combinaison de points de code constitue un graphème. Heureusement, il en existe un: le grapheme-splitter d' Orling . Vous voudrez l'installer avec npm ou, si vous n'utilisez pas npm, télécharger le fichier index.js et le servir avec une <script>balise. Pour cette démo, je vais le charger depuis jsDelivr.

graphème-séparateur nous donne une GraphemeSplitterclasse avec trois méthodes: splitGraphemes, iterateGraphemeset countGraphemes. Naturellement, nous voulons splitGraphemes:

const splitter = new GraphemeSplitter();
const yourString = 'Á🇬🇧👩🏿';
const charArray = splitter.splitGraphemes(yourString);
console.log(charArray);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/index.js"></script>

Et nous y sommes - un tableau de trois graphèmes, ce qui est probablement ce que vous vouliez.

Mark Amery
la source
2

Vous pouvez parcourir la longueur de la chaîne et pousser le caractère à chaque position :

const str = 'Hello World';

const stringToArray = (text) => {
  var chars = [];
  for (var i = 0; i < text.length; i++) {
    chars.push(text[i]);
  }
  return chars
}

console.log(stringToArray(str))

Mohit Rathore
la source
1
Bien que cette approche soit un peu plus impérative que déclarative, c'est la plus performante de toutes dans ce fil et mérite plus d'amour. Une limitation à la récupération d'un caractère sur une chaîne par position est lorsque vous traitez des caractères au-delà du plan multilingue de base en unicode tels que les emojis. "😃".charAt(0)rendra un personnage inutilisable
KyleMit
2
@KyleMit, cela ne semble vrai que pour une courte entrée. Utiliser une entrée plus longue rend à .split("")nouveau l'option la plus rapide
Lux
1
.split("")Semble également être fortement optimisé dans Firefox. Alors que la boucle a des performances similaires dans Chrome, la séparation de Firefox est nettement plus rapide dans Firefox pour les petites et grandes entrées.
Lux
2

réponse simple:

let str = 'this is string, length is >26';

console.log([...str]);

ajit kumar
la source
-1; cela n'ajoute rien qui n'était pas déjà inclus dans la réponse de hakatashi .
Mark Amery
0

Une possibilité est la suivante:

console.log([1, 2, 3].map(e => Math.random().toString(36).slice(2)).join('').split('').map(e => Math.random() > 0.5 ? e.toUpperCase() : e).join(''));
user2301515
la source
-1

Que dis-tu de ça?

function stringToArray(string) {
  let length = string.length;
  let array = new Array(length);
  while (length--) {
    array[length] = string[length];
  }
  return array;
}
msand
la source
@KyleMit cela semble plus rapide que pour i loop + push jsperf.com/string-to-character-array/3
ms et
-1

Array.prototype.slice fera également le travail.

const result = Array.prototype.slice.call("Hello world!");
console.log(result);

f3tknco
la source