JavaScript'te bir karakter dizisine bir dize nasıl alırsınız?


369

Bir dizeyi JavaScript'te bir karakter dizisine nasıl dönüştürürsünüz?

"Hello world!"Dizi gibi bir dize almayı düşünüyorum
['H','e','l','l','o',' ','w','o','r','l','d','!']

Yanıtlar:


492

Not: Bu unicode uyumlu değildir. tehlikeli "I💖U".split('')karakterlere ["I", "�", "�", "u"]yol açabilecek 4 karakter dizisiyle sonuçlanır. Güvenli alternatifler için aşağıdaki yanıtlara bakın.

Boş bir dize ile bölün.

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

String.prototype.split()MDN belgelerine bakın .


31
Bu vekil çiftleri hesaba katmaz. "𨭎".split('')ile sonuçlanır ["�", "�"].
hippietrail

59
Bu konudaki başka bir yerde @ hakatashi'nin cevabına bakınız. Umarım herkes bunu görür ... BU YÖNTEMİ KULLANMAYIN, GÜVENLİ BİR UNICODE DEĞİL
i336_

3
Partiye biraz geç. Ama neden birileri bir dizi dizge yapmak istesin ki? Bir dize zaten bir dizi veya yanlış mıyım? "randomstring".length; //12 "randomstring"[2]; //"n"
Luigi van Pal der

4
@LuigivanderPal Bir dize bir dizi değildir, ancak çok benzerdir. Ancak, bir karakter dizisine benzemez. Bir dize, bazıları karakterleri temsil eden ve bazıları bir vekil çiftin yarısını temsil eden 16 bitlik sayı dizisine benzer. Örneğin, str.lengthbazı karakterler diğerlerinden daha fazla yer kapladığından, dizedeki karakter sayısını size söylemez; str.lengthsize 16 bitlik sayıların sayısını söyler.
Theodore Norvell

289

Gibi hippietrail anlaşılacağı , Meder cevabı vekil çiftleri ve yanlış anlaşılabilir kırabilir “karakterlerini.” Örneğin:

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

Bu karakter dizilerini doğru şekilde işlemek için aşağıdaki ES2015 özelliklerinden birini kullanmanızı öneririm.

Spread sözdizimi ( insertusernamehere tarafından zaten cevaplanmıştır )

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

Array.from

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

RegExp ubayrağı

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

Kullanım /(?=[\s\S])/uyerine /(?=.)/uçünkü .yeni satır uymuyor .

Hala ES5.1 çağındaysanız (veya tarayıcınız bu regex'i Edge gibi doğru şekilde işlemiyorsa ) bu alternatifi kullanabilirsiniz ( Babel tarafından aktarılır ):

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

Unutmayın ki Babel, eşsiz vekilleri doğru bir şekilde ele almaya çalışmaktadır. Ancak, bu eşsiz düşük taşıyıcılar için işe yaramıyor gibi görünüyor.

Tarayıcınızda tümünü test edin:


Bu karakterleri nasıl oluşturdunuz? Her karakterin 4 bayt olduğu anlaşılıyor.
user420667

2
@ user420667 karakterler "büyük" kod noktaları olan ek bir karakter düzleminden (unicode tablosunda) gelir, bu nedenle 16 bayta sığmazlar. Javascript'te kullanılan utf-16 kodlaması, bu karakterleri vekil çiftler olarak sunar (yalnızca ek düzlemlerden başka karakterler oluşturmak için çift olarak kullanılan özel karakterler). Sadece ana karakter düzlemindeki karakterler 16 bayt ile sunulur. Surrugate çifti özel karakterleri de, eğer yaparsa, ana karakter düzleminden.
Olga

1
Farklı tekniklerin performansı , yayılan op şampiyona benziyor (krom 58).
Adrien

4
Bu çözümün 🏳️‍🌈, karakterlerdeki aksan işaretlerini birleştiren gibi bazı emojiler ayırdığını unutmayın . Karakterler yerine grafik kümelerine bölünmek istiyorsanız, bkz. Stackoverflow.com/a/45238376 .
user202729

3
Yedek çiftleri parçalamamak harika olsa da, "karakterleri" (veya daha doğru bir şekilde, grafikleri ) bir arada tutmak için genel amaçlı bir çözüm olmadığını unutmayın . Bir grafik birden fazla kod noktasından oluşabilir; Örneğin, Devanagari dilinin adı, yerli bir konuşmacı tarafından beş grafik olarak okunan "देवनागरी" dir, ancak üretmek için sekiz kod noktası alır ...
TJ Crowder

71

spreadSözdizimi

ECMAScript 2015 (ES6) standardında tanıtılan bir Array Initializer olan forma sözdizimini kullanabilirsiniz :

var arr = [...str];

Örnekler

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

İlk üç sonuç:

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

Sonuncusu

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

Tarayıcı Desteği

ECMAScript ES6 uyumluluk tablosunu kontrol edin .


daha fazla okuma

spread" splat" (örn. PHP veya Ruby'de veya " scatter" olarak da adlandırılır (örneğin Python'da ).


gösteri

Satın almadan önce deneyin


1
ES5 için bir derleyici ile birlikte forma operatörü kullanırsanız bu IE çalışmaz. Bunu göz önünde bulundurun. Sorunun ne olduğunu anlamak saatlerimi aldı.
Stef van den Berg

13

Ayrıca kullanabilirsiniz Array.from.

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

Bu yöntem ES6'da tanıtıldı.

Referans

Array.from


10

Bu eski bir soru ama henüz listelenmemiş başka bir çözümle karşılaştım.

İstenen çıktıyı elde etmek için Object.assign işlevini kullanabilirsiniz:

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

Mutlaka doğru ya da yanlış değil, sadece başka bir seçenek.

Object.assign, MDN sitesinde iyi tanımlanmıştır.


2
Ulaşmak için çok yol var Array.from("Hello, world").
TJ Crowder

@TJCrowder Almak için uzun bir yol[..."Hello, world"]
chharvey

@chharvey - Heh. :-)
TJ Crowder

9

Zaten:

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

Veya daha eski bir tarayıcı dostu sürüm için şunu kullanın:

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


4
-1: değil. Deneyin:alert("Hello world!" == ['H','e','l','l','o',' ','w','o','r','l','d'])
R. Martinho Fernandes

4
Afedersiniz. Ne demek istediğimi tahmin ediyorum: "bir karakter dizisi oluşturmadan böyle dizin referansı ile tek tek karakterlere erişebilirsiniz".
dansimau

3
Güvenilir değil çapraz tarayıcı yapamazsınız. ECMAScript Beşinci Baskı özelliğidir.
bobince

8
Çapraz tarayıcı sürümü mystring.charAt(index).
psmay

1
+1 için - charAt()dizi-ish değişkenini kullanmayı tercih etsem de. Lanet IE.
Zenexer

4

Bir "karakter" olarak düşünebileceğiniz (en azından) üç farklı şey ve sonuç olarak kullanmak isteyebileceğiniz üç farklı yaklaşım kategorisi vardır.

UTF-16 kod birimlerine bölme

JavaScript dizeleri, UTF-16 kod birimleri ile Unicode kod noktaları arasında bire bir ilişki olduğunda, geçmişte bir noktada UTF-16 kod birimlerinin dizileri olarak icat edildi. .lengthBir dize özellik UTF-16 kod birimleri uzunluğunu ölçer ve bunu yaptığında someString[i]almak i th UTF-16 kod birimi someString.

Sonuç olarak, bir dizin değişkenli bir C stili for-loop kullanarak bir dizeden UTF-16 kod birimleri dizisi alabilirsiniz ...

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

Aynı şeyi elde etmenin çeşitli kısa yolları da vardır, örneğin .split()boş dize ile ayırıcı olarak kullanmak:

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

Bununla birlikte, dizeniz birden fazla UTF-16 kod biriminden oluşan kod noktaları içeriyorsa, bu kodlar bunları tek tek kod birimlerine böler; Örneğin, dize '𝟘𝟙𝟚𝟛'UTF-16'da her biri iki UTF-16 kod biriminden oluşan dört adet unicode kod noktasından (kod noktaları 0x1D7D8 - 0x1D7DB) oluşur. Bu dizeyi yukarıdaki yöntemleri kullanarak bölersek, sekiz kodluk bir dizi alırız:

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

Unicode Kod Noktalarına Bölme

Belki de dizemizi Unicode Kod Noktalarına bölmek istiyoruz! ECMAScript 2015 , dile yinelenebilir bir kavram eklediğinden bu mümkün oldu . Dizeler artık yinelenebilir ve üzerlerinde yineleme yaptığınızda (örneğin bir for...ofdöngü ile), UTF-16 kod birimleri yerine Unicode kod noktaları elde edersiniz:

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

Array.fromÖrtük olarak geçirildiği yinelenebilir üzerinde yinelenen bu kullanımı kısaltabiliriz :

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

Ancak, unicode kod noktaları "karakter" olarak da düşünülebilecek olası en büyük şey değildir . Tek bir "karakter" olarak düşünülebilecek, ancak birden fazla kod noktasından oluşabilecek bazı örneklere şunlar dahildir:

  • Vurgu bir birleştirme kod noktasıyla uygulanırsa aksanlı karakterler
  • Bayraklar
  • Bazı emojiler

Aşağıda, bu tür karakterleri olan bir dizeyi yukarıdaki yineleme mekanizması aracılığıyla bir diziye dönüştürmeye çalışırsak, sonuçta oluşan dizide karakterlerin parçalandığını görebiliriz. (Karakterlerin herhangi birinin sisteminizde görüntülenmemesi durumunda, yourStringaşağıda akut aksanlı bir başkent A , ardından İngiltere bayrağı ve ardından siyah bir kadın bulunur.)

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

Bunların her birini son dizimizde tek bir öğe olarak tutmak istiyorsak , kod noktalarına değil , bir grafik dizisine ihtiyacımız var .

Grafiklere bölme

JavaScript'in bunun için yerleşik bir desteği yoktur - en azından henüz. Bu nedenle, Unicode kurallarını anlayan ve uygulayan bir kitaplığa ihtiyacımız var. Neyse ki, biri var: orling'in grapheme-splitter . Npm ile yüklemek veya npm kullanmıyorsanız index.js dosyasını indirin ve bir <script>etiketle sunun . Bu demo için jsDelivr'den yükleyeceğim.

sesletim-ayırıcı bize verir GraphemeSplitter: üç yöntemleri ile sınıf splitGraphemes, iterateGraphemesve countGraphemes. Doğal olarak istiyoruz splitGraphemes:

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

Ve işte buradayız - muhtemelen istediğin şey olan üç grafik dizisi .


2

Dizenin uzunluğu boyunca yineleme yapabilir ve karakteri her bir konuma itebilirsiniz :

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


1
Bu yaklaşım, deklaratif olmaktan biraz daha zorunlu olmakla birlikte, bu konudaki en iyi performans ve daha fazla sevgiyi hak ediyor. Bir sınırlama için konumuna göre bir dize bir karakter alınırken geçmiş karakterler ile uğraşırken olan Temel Dilde Plan böyle emoji'yi olarak unicode. "😃".charAt(0)kullanılamaz bir karakter döndürür
KyleMit

2
@KyleMit bu sadece kısa bir girdi için geçerli gibi görünüyor. Daha uzun bir giriş kullanmak .split("")en hızlı seçeneği tekrar yapar
Lux

1
Ayrıca .split("")firefox'ta büyük ölçüde optimize edilmiş gibi görünüyor. Döngü kromda benzer performansa sahipken, firefox bölmesi firefox'ta küçük ve büyük girdiler için önemli ölçüde daha hızlıdır.
Lux


0

Bir olasılık bir sonraki:

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


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.