Wie erhält man eine Zeichenfolge zu einem Zeichenarray in JavaScript?

369

Wie konvertiert man eine Zeichenfolge in ein Zeichenarray in JavaScript?

Ich denke, einen String wie "Hello world!"das Array zu bekommen
['H','e','l','l','o',' ','w','o','r','l','d','!']

DarkLightA
quelle

Antworten:

492

Hinweis: Dies ist nicht Unicode-kompatibel. "I💖U".split('')führt zu einem 4-Zeichen-Array, ["I", "�", "�", "u"]das zu gefährlichen Fehlern führen kann. In den Antworten unten finden Sie sichere Alternativen.

Teilen Sie es einfach durch eine leere Zeichenfolge.

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

Siehe die String.prototype.split()MDN-Dokumente .

meder omuraliev
quelle
31
Dies berücksichtigt keine Ersatzpaare. "𨭎".split('')führt zu ["�", "�"].
Hippietrail
59
Siehe @ hakatashis Antwort an anderer Stelle in diesem Thread. Hoffentlich sieht das jeder ...
VERWENDEN SIE DIESE
3
Etwas spät zur Party. Aber warum sollte jemand jemals ein Array aus einem String erstellen wollen? Ein String ist bereits ein Array oder irre ich mich? "randomstring".length; //12 "randomstring"[2]; //"n"
Luigi van der Pal
4
@LuigivanderPal Ein String ist kein Array, aber sehr ähnlich. Es ähnelt jedoch nicht einem Array von Zeichen. Eine Zeichenfolge ähnelt einem Array von 16-Bit-Zahlen, von denen einige Zeichen und einige die Hälfte eines Ersatzpaars darstellen. Gibt beispielsweise str.lengthnicht die Anzahl der Zeichen in der Zeichenfolge an, da einige Zeichen mehr Platz beanspruchen als andere. str.lengthgibt Ihnen die Anzahl der 16-Bit-Zahlen an.
Theodore Norvell
289

Wie Hippietrail vorschlägt , kann die Antwort des Meders Ersatzpaare brechen und „Zeichen“ falsch interpretieren. Zum Beispiel:

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

Ich schlage vor, eine der folgenden ES2015-Funktionen zu verwenden, um diese Zeichenfolgen korrekt zu handhaben.

Spread-Syntax ( bereits von insertusernamehere beantwortet )

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

Array.from

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

RegExp- uFlag

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

Verwenden Sie /(?=[\s\S])/uanstelle von " /(?=.)/uweil" .nicht mit Zeilenumbrüchen übereinstimmt .

Wenn Sie sich noch in der ES5.1-Ära befinden (oder wenn Ihr Browser diesen regulären Ausdruck nicht richtig verarbeitet - wie Edge), können Sie diese Alternative verwenden (von Babel transpiliert ):

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

Beachten Sie, dass Babel versucht, auch nicht übereinstimmende Surrogate korrekt zu behandeln. Dies scheint jedoch nicht für unübertroffene niedrige Surrogate zu funktionieren.

Testen Sie alles in Ihrem Browser:

Hakatashi
quelle
Wie hast du diese Charaktere geformt? Es sieht so aus, als ob jedes Zeichen 4 Bytes groß ist.
user420667
2
@ user420667 Die Zeichen stammen aus einer zusätzlichen Zeichenebene (in der Unicode-Tabelle) mit "großen" Codepunkten, daher passen sie nicht in 16 Bytes. Die in Javascript verwendete utf-16-Codierung präsentiert diese Zeichen als Ersatzpaare (Sonderzeichen, die nur als Paare verwendet werden, um andere Zeichen aus zusätzlichen Ebenen zu bilden). Nur die Zeichen der Hauptcharachterebene werden mit 16 Bytes dargestellt. Surrugate-Paar-Sonderzeichen stammen ebenfalls aus der Hauptcharakterebene, wenn dies sinnvoll ist.
Olga
1
Die Leistung der verschiedenen Techniken , Spread Op sieht aus wie der Champion (Chrom 58).
Adrien
4
Beachten Sie, dass diese Lösung einige Emoji wie 🏳️‍🌈und die Kombination von diakritischen Zeichen von Zeichen aufteilt . Wenn Sie anstelle von Zeichen in Graphemcluster aufteilen möchten, lesen Sie stackoverflow.com/a/45238376 .
user202729
3
Beachten Sie, dass es zwar großartig ist, Ersatzpaare nicht auseinanderzubrechen, aber keine universelle Lösung ist, um "Zeichen" (oder genauer Grapheme ) zusammenzuhalten. Ein Graphem kann aus mehreren Codepunkten bestehen. Zum Beispiel ist der Name der Sprache Devanagari "देवनागरी", die von einem Muttersprachler als fünf Grapheme gelesen wird, aber acht Codepunkte benötigt, um ...
TJ Crowder
71

Die spreadSyntax

Sie können die Spread-Syntax verwenden , einen Array-Initialisierer, der im ECMAScript 2015 (ES6) -Standard eingeführt wurde :

var arr = [...str];

Beispiele

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

Die ersten drei ergeben:

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

Der letzte ergibt

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

Browser-Unterstützung

Überprüfen Sie die ECMAScript ES6-Kompatibilitätstabelle .


Weiterführende Literatur

spreadwird auch als " splat" (z. B. in PHP oder Ruby oder als " scatter" (z . B. in Python ) bezeichnet.


Demo

Versuchen Sie es vor dem Kauf

insertusernamehere
quelle
1
Wenn Sie den Spread-Operator in Kombination mit einem Compiler für ES5 verwenden, funktioniert dies im IE nicht. Berücksichtigen Sie das. Ich habe Stunden gebraucht, um herauszufinden, wo das Problem lag.
Stef van den Berg
13

Sie können auch verwenden Array.from.

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

Diese Methode wurde in ES6 eingeführt.

Referenz

Array.from

Rajesh
quelle
10

Dies ist eine alte Frage, aber ich bin auf eine andere Lösung gestoßen, die noch nicht aufgeführt ist.

Mit der Object.assign-Funktion können Sie die gewünschte Ausgabe erhalten:

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

Nicht unbedingt richtig oder falsch, nur eine andere Option.

Object.assign wird am MDN-Standort gut beschrieben.

David Thomas
quelle
2
Das ist ein langer Weg Array.from("Hello, world").
TJ Crowder
@TJCrowder Das ist ein langer Weg zu[..."Hello, world"]
chharvey
@chharvey - Heh. :-)
TJ Crowder
9

Es ist schon:

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

Oder verwenden Sie für eine ältere browserfreundliche Version:

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

Dansimau
quelle
4
-1: ist es nicht. Probieren Sie es aus:alert("Hello world!" == ['H','e','l','l','o',' ','w','o','r','l','d'])
R. Martinho Fernandes
4
Es tut uns leid. Ich denke, was ich damit sagen wollte, ist: "Sie können auf einzelne Zeichen durch eine Indexreferenz wie diese zugreifen, ohne ein Zeichenarray zu erstellen".
Dansimau
3
Nicht zuverlässig browserübergreifend können Sie nicht. Es ist eine ECMAScript Fifth Edition-Funktion.
Bobince
8
Die browserübergreifende Version ist mystring.charAt(index).
Mai
1
+1 für - charAt()obwohl ich lieber die Array-Variante verwenden würde. Verdammter IE.
Zenexer
4

Es gibt (mindestens) drei verschiedene Dinge, die Sie sich als "Charakter" vorstellen können, und folglich drei verschiedene Kategorien von Ansätzen, die Sie möglicherweise verwenden möchten.

Aufteilung in UTF-16-Codeeinheiten

JavaScript-Zeichenfolgen wurden ursprünglich als Sequenzen von UTF-16-Codeeinheiten erfunden, zu einem Zeitpunkt in der Geschichte, als es eine Eins-zu-Eins-Beziehung zwischen UTF-16-Codeeinheiten und Unicode-Codepunkten gab. Die .lengthEigenschaft eines Strings misst seine Länge in UTF-16-Codeeinheiten, und wenn Sie dies tun, erhalten someString[i]Sie die i- te UTF-16-Codeeinheit von someString.

Folglich können Sie ein Array von UTF-16-Codeeinheiten aus einer Zeichenfolge abrufen, indem Sie eine for-Schleife im C-Stil mit einer Indexvariablen verwenden ...

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

Es gibt auch verschiedene kurze Möglichkeiten, um dasselbe zu erreichen, z. B. die Verwendung .split()der leeren Zeichenfolge als Trennzeichen:

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

Wenn Ihre Zeichenfolge jedoch Codepunkte enthält, die aus mehreren UTF-16-Codeeinheiten bestehen, werden diese in einzelne Codeeinheiten aufgeteilt, die möglicherweise nicht Ihren Wünschen entsprechen. Beispielsweise besteht die Zeichenfolge '𝟘𝟙𝟚𝟛'aus vier Unicode-Codepunkten (Codepunkte 0x1D7D8 bis 0x1D7DB), die in UTF-16 jeweils aus zwei UTF-16-Codeeinheiten bestehen. Wenn wir diese Zeichenfolge mit den oben beschriebenen Methoden aufteilen, erhalten wir ein Array mit acht Codeeinheiten:

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

Aufteilen in Unicode-Codepunkte

Vielleicht möchten wir stattdessen unsere Zeichenfolge in Unicode-Codepunkte aufteilen! Dies ist möglich, seit ECMAScript 2015 der Sprache das Konzept einer Iterierbarkeit hinzugefügt hat . Strings sind jetzt iterabel, und wenn Sie sie durchlaufen (z. B. mit einer for...ofSchleife), erhalten Sie Unicode-Codepunkte, keine UTF-16-Codeeinheiten:

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

Wir können dies verkürzen, indem wir Array.fromüber das Iterable iterieren, das implizit übergeben wird:

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

Unicode-Codepunkte sind jedoch nicht die größtmögliche Sache, die möglicherweise auch als "Zeichen" betrachtet werden könnte . Einige Beispiele für Dinge, die vernünftigerweise als ein einziges "Zeichen" betrachtet werden könnten, aber aus mehreren Codepunkten bestehen, sind:

  • Akzentzeichen, wenn der Akzent mit einem kombinierten Codepunkt angewendet wird
  • Flaggen
  • Einige Emojis

Wir können unten sehen, dass, wenn wir versuchen, eine Zeichenfolge mit solchen Zeichen über den obigen Iterationsmechanismus in ein Array zu konvertieren, die Zeichen im resultierenden Array aufgelöst werden. (Falls eines der Zeichen in Ihrem System nicht gerendert wird, yourStringbesteht es unten aus einem Großbuchstaben A mit akutem Akzent, gefolgt von der Flagge des Vereinigten Königreichs, gefolgt von einer schwarzen Frau.)

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

Wenn wir jedes dieser Elemente als einzelnes Element in unserem endgültigen Array behalten möchten, benötigen wir ein Array von Graphemen , keine Codepunkte.

Aufteilung in Grapheme

JavaScript hat keine integrierte Unterstützung dafür - zumindest noch nicht. Wir brauchen also eine Bibliothek, die die Unicode-Regeln versteht und implementiert, für welche Kombination von Codepunkten ein Graphem besteht. Zum Glück gibt es eines: Orlings Graphemspalter . Sie möchten es mit npm installieren oder, wenn Sie npm nicht verwenden, die Datei index.js herunterladen und mit einem <script>Tag versehen. Für diese Demo werde ich es von jsDelivr laden.

Graphem-Splitter gibt uns eine GraphemeSplitterKlasse mit drei Methoden: splitGraphemes, iterateGraphemes, und countGraphemes. Natürlich wollen wir 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>

Und da sind wir - eine Reihe von drei Graphemen, was Sie wahrscheinlich wollten.

Mark Amery
quelle
2

Sie können über die Länge der Zeichenfolge iterieren und das Zeichen an jeder Position verschieben :

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
quelle
1
Während dieser Ansatz ein wenig zwingender als deklarativ ist, ist er der performanteste in diesem Thread und verdient mehr Liebe. Eine Einschränkung beim Abrufen eines Zeichens in einer Zeichenfolge nach Position besteht darin, dass Zeichen nach dem mehrsprachigen Basisplan in Unicode wie Emojis behandelt werden. "😃".charAt(0)wird einen unbrauchbaren Charakter zurückgeben
KyleMit
2
@KyleMit dies scheint nur für eine kurze Eingabe zu gelten. Die Verwendung eines längeren Eingangs ist wieder .split("")die schnellste Option
Lux
1
Auch .split("")scheint in Firefox stark optimiert werden. Während die Schleife eine ähnliche Leistung in Chrom und Firefox aufweist, ist die Aufteilung in Firefox für kleine und große Eingaben erheblich schneller.
Lux
0

Eine Möglichkeit ist die nächste:

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
quelle
-1

Wie wäre es damit?

function stringToArray(string) {
  let length = string.length;
  let array = new Array(length);
  while (length--) {
    array[length] = string[length];
  }
  return array;
}
msand
quelle
@ KyleMit dies scheint schneller als für i loop + push jsperf.com/string-to-character-array/3
msand