Javascript kullanarak her bir metin harfini nasıl işleyebilirim?


363

Bir dizenin her harfini uyarmak istiyorum, ama bunu nasıl yapacağımdan emin değilim.

Yani, eğer varsa:

var str = 'This is my string';

T, h, i, s, vb.

JQuery kullanmak istiyorum ve dizenin uzunluğu ne olduğunu test ettikten sonra split işlevini kullanmak gerekebilir düşünüyorum.

Fikirler?


3
Belki de bunu arıyordunuz: ES6'dan itibaren var for(const c of str) { ... }. Bunlardan daha fazlası, oldukça ayrıntılı ancak yeterince yükseltilmemiş bir cevapta. Not: @ ARJUN'un bağlantısı benim için çalışmıyor.
Max

Yanıtlar:


421

Uyarıların sırası önemliyse, şunu kullanın:

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

Uyarıların sırası önemli değilse, bunu kullanın:

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


2
[]char'ı belirli bir pozisyonda almak için kullanılması IE <9
vsync'de

13
diğer cevapta da belirtildiği gibi, [] 'ler yerine str.charAt (i) kullanabilirsiniz. neden charAt vs [] kullanmanız gerektiği hakkında daha fazla bilgi için bkz. string.charAt (x) veya string [x]
Julian Soro

12
Dize döngü içinde değiştirilmemişse, herhangi bir modern JS derleyici uzunluğu yeniden hesaplamak inanmak zor buluyorum. Diğer tüm dillerde, derleyicinin en iyi bildiği ve buna göre optimize edeceği varsayılarak, for döngüsünün test maddesindeki uzunluk kontrolünü mutlulukla yaparım.
Echelon

3
@Dagmar: Javascript UTF-8 kullanmaz, UTF-16 (veya tarayıcıya bağlı olarak UCS-2) kullanır. Her karakter UTF-8 veya UTF-16 olarak temsil edilebilir, ancak bu problemi yaşamaz. Problemi olan sadece UTF-16'da iki bayt yerine dört bayt gerektirenlerdir. 💩 UTF-16'da dört bayt gerektiren bir karakterdir. Daha fazla bilgi aramak için anahtar terimler "astral düzlem", "BMP dışı" ve "vekil çifti" dir.
hippietrail

1
@Dagmar: Java ve Javascript'in ortak UTF-16 (eski adıyla UCS-) vardır. Bunu kullanan üçüncü büyük platform Windows'tur. Unix, MacOS ve internet protokolleri UTF-8 kullanır. charAtvekil çiftin olmadığı ve problemi çözmek için UCS-2 günlerinden ayrıldı ve yeni bir fonksiyon, codepointAtdostane kaka yığınımızı doğru şekilde işleyen JavaScript'e eklendi. Java'nın da buna sahip olduğuna inanıyorum.
hippietrail

241

Muhtemelen çözülmekten daha fazlasıdır. Başka bir basit çözümle katkıda bulunmak istiyorsanız:

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

4
son örnek sadece olabilir[...text].forEach(console.log)
Govind Rai

10
Hayır, olamaz. forEach()dizini ve diziyi ikinci ve üçüncü bağımsız değişken olarak geçirir. Bunu günlüğe
kaydetmek istemem

1
Hem yayılma işlecinin (ilk örnek) hem de bölünmüş aramanın (son örnek) yeni bir dizi oluşturacağını unutmayın. Bu genellikle bir sorun olmayacaktır, ancak büyük dizeler veya sık kullanımlar için maliyetli olabilir.
Randolpho

Peki yafor (let c of [...text]) { console.log(c) }
Flimm

Bununla dizeden yeni bir dizi oluşturursunuz. Avantajı görmüyorum. let c of textişi zaten yapıyor.
Bay Goferito

73

Saf javascriptte olası bir çözüm:

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

Muhtemelen var x = 0 ve var c = str.charAt (x) ile daha iyi olurdu.
Zengin

2
Ayrıca, str.length değerinin erişilebilmesi için bir değişkende saklanması gerekir.
Eli Gray

8
@EliGrey Bir değişkene uzunluk koymak gerçekten önemli mi? Bunun daha az kod satırına göre ne zaman tercih edilebileceğine dair ölçütleriniz var mı?
pm_labs

@paul_sns İlginç bir şekilde , en azından Edge'de (10000 eleman dizisi için 0.7 ms fark) küçük bir fark var gibi görünüyor : jsfiddle.net/carcigenicate/v8vvjoc1/1 . Muhtemelen mükemmel bir test değildir, ancak ortalama 10000 teste dayanmaktadır.
Carcigenicate

1
@paul_sns Ayrıca ilginç bir şekilde, Chrome aynı testi yaklaşık% 2 oranında gerçekleştirdi (~ 5ms ve ~ 0.0997ms) ve her iki sürüm de aynı zamanı verdi, bu yüzden Edge optimize edilmemiş gibi görünüyor.
Carcigenicate

69

Her metin mektubu nasıl işlenir (kıyaslamalarla)

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

için

Klasik ve açık ara en yüksek performansa sahip olanı . Performans açısından kritik bir algoritmada kullanmayı planlıyorsanız veya tarayıcı sürümleriyle maksimum uyumluluk gerektiriyorsa, bununla gitmelisiniz.

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

Türk pazarına ...

için ... yineleyici için yeni ES6 . Çoğu modern tarayıcı tarafından desteklenir. Görsel olarak daha çekici ve yazım hatalarına daha az eğilimlidir. Bunu bir üretim uygulamasında yapacaksanız, muhtemelen Babel gibi bir transpiler kullanmalısınız .

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

her biri için

İşlevsel yaklaşım. Airbnb onayladı . Bunu bu şekilde yapmanın en büyük dezavantajı split(), dizenin her harfini saklamak için yeni bir dizi yaratır.

Neden? Bu değişmez kuralımızı zorlar. Değerleri döndüren saf işlevlerle başa çıkmak, yan etkilerden daha kolaydır.

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

veya

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

Sevmediğim şeyler aşağıdadır.

için ... lütfen

... için farklı olarak, harf yerine harf dizinini alırsınız. Oldukça kötü bir performans sergiliyor.

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

map

İyi olan fonksiyon yaklaşımı. Ancak, haritanın bunun için kullanılması amaçlanmamıştır. Bir dizinin içindeki değerleri değiştirmek gerektiğinde kullanılmalıdır (durum böyle değildir).

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

veya

let result = '';
str.split('').map(function(letter) {
  result += letter;
});

1
Makinemde klasik fordöngü aslında ikinci en yavaş, for...ofen hızlıydı (yaklaşık üç kat daha hızlı for).
John Montgomery

1
Kıyaslama nerede? En hızlı çözüm nedir?
poitroae

1
@johnywhy Bu iki yıl önceydi ve bağlantı öldü, o zaman geri döndüğüm sonucu nasıl savunmamı beklediğinizden emin değilim. Yine de, yeni bir karşılaştırma ölçütü oluşturmak, fordöngü biraz daha hızlı olduğu için zurfyx'in sonucunu kabul ediyor .
John Montgomery

1
@JohnMontgomery Hiçbir şey yapmanı beklemiyorum. Gelecekteki okuyuculara, sonuçlarınızın yanıttan farklı olduğuna dair bir not. Şahsen ben bugün 2020 tarayıcıları için hangi sonuçların geçerli olduğunu bilmek istiyorum, 2018 uzun zaman önce değildi. Hangi bağlantı öldü?
johny neden

1
@johnywhy Tüm gerçek testlerle en üstteki bağlantı benim için 404 döndürüyor.
John Montgomery

42

Buradaki cevapların tümü yanlış olmasa da çoğu Unicode BMP (Temel Çok Dilli Düzlem) dışındaki dizede bir karakter olduğunda kırılacaktır . Bu, tüm Emoji'lerin kırılacağı anlamına gelir .

JavaScript, tüm dizeler için UTF- 16 Unicode kullanır . UTF-16'da, BMP'nin ötesindeki karakterler " Yedek Çift " olarak adlandırılan iki bölümden oluşur ve buradaki cevapların çoğu, bu çiftlerin her bir parçasını tek bir karakter yerine ayrı ayrı işleyecektir.

En az 2016'dan beri modern JavaScript'te bir yol, yeni String yineleyiciyi kullanmaktır . İşte (neredeyse) doğrudan MDN'den örnek:

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"


4
Yedek çiftleri dikkate alırken bir dizeyi karakterlere bölmenin modern bir çözümü için bkz. Stackoverflow.com/a/42596897/527702
hippietrail

20

Bunu deneyebilirsin

var arrValues = 'This is my string'.split('');
// Loop over each value in the array.
$.each(arrValues, function (intIndex, objValue) {
    alert(objValue);
})

11
Hala bir seçenek, ama performans değil. JQuery'yi her yere koymayın.
cagatay

10

Bir çözüm daha ...

var strg= 'This is my string';
for(indx in strg){
  alert(strg[indx]);
}

3
Dizini değil, yalnızca karakteri istiyorsanız, bir for..ofdöngü kullanmak daha hızlı olurdufor (let ch of t) { alert(ch) }
Shaheen Ghiassy

10

Kısa kod veya bir astar yazmak gerektiğinde, bu "kesmek" kullanın:

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

Bu yeni satırları saymaz, böylece iyi ya da kötü bir şey olabilir. Hangi satırsonu ekleyecekseniz: /./ile değiştirin /[\S\s]/. Muhtemelen kullanabileceğiniz , birçok sorunu.split() olan diğer tek gömlekler


en iyi cevap. Unicode ile ilgili problemleri dikkate alır ve ayrıca .map () vb.
İle

Bu konuda sevmediğim tek şey , forEachçağrının işlevine gönderilen replaceekstra parametrelere vs gönderilen paramlara erişmek istediğim zamandır . ASCIIing olduğumu biliyorsam, hala bazı kullanım durumlarım olduğunu düşünüyorum split. Yine de harika bir cevap!
17'de ruffin

Bu cevap, yine de kontrol edeceğiniz değerlerin önceden seçilmesiyle bonusa sahiptir
Fuzzyma

1
Ben vardı sürece bu hesaba Unicode sorunları almayacağını düşündük ubirlikte bayrak gbayrak? Tamam sadece test ve haklıydım.
hippietrail

9

Yeni JS buna izin verir:

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

8

Dize unicode karakterler içeriyorsa, farklı bayt boyutu nedeniyle for ... ifadesini kullanmak daha iyidir.

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

7

kısa cevap: Array.from(string)size muhtemelen ne istediğinizi verecektir ve daha sonra sadece bir dizi olduğu için veya üzerinde tekrarlayabilirsiniz.

ok'un bu dize ile deneyelim: abc|⚫️\n⚪️|👨‍👩‍👧‍👧.

kod noktaları:

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

bu yüzden bazı karakterlerin bir kod noktası (bayt) ve bazılarında iki veya daha fazla ve ekstra test için yeni satır eklenir.

test ettikten sonra iki yol var:

  • bayt başına bayt (kod noktası başına kod noktası)
  • karakter grupları (ancak tüm aile emojileri değil)

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


7

Şimdi, bir Dize'de yer alan tek tek Unicode kod noktaları üzerinde, yinelenen String.prototype[@@iterator]bir Sembol türü değeri olan Symbol.iteratordizi benzeri Nesneler için varsayılan yineleyici ( Stringbu durumda) döndüren değerini kullanarak yineleyebilirsiniz .

Örnek kod:

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.

Bu, eski yapıları açacak olan emoji veya roman olmayan karakterler gibi Unicode karakterlerle çalışır.

Referans: MDN : String.prototype @@ iterator bağlantısı .


2
Bunu for ... of, yineleyiciye erişmek için sözdizimi şekeri olan bir döngü ile de daha kısa bir şekilde yapabileceğinizi unutmayın .
Aditya MP

6

Artık kullanabilirsiniz içinde anahtar kelime.

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


Filtrelenmediğinde kullanmak kötü bir uygulama ve korkunç. Buna karşı şiddetle tavsiye ediyorum
Downgoat

4
@Downgoat neden? Bunun nesi kötü? Yani, 'in' in Javascript motorum tarafından desteklendiğini ve kodumun başka bir motora giden yolu bulamayacağını bildiğim bir durumdaysam ... neden bunu kullanmıyorsunuz?
TKoL

Bkz @TKoL bu .
Alan

@Alan in, dilin meşru bir parçasıdır. İşleri uygun şekilde kullanın. Makaleniz, inalfa tuşlarını sayısal tuşlarla aynı şekilde yorumlar. Yani? Belki de bunu istersiniz. Diğer yöntemlerin alfa tuşlarını yanlış göz ardı ettiği de söylenebilir . Imo, ofdoğru davranışa sahip. JS dizilerinde, alfa anahtarları olmayan öğelerin hala anahtarları vardır: sayısal olanlar. Konsolumda, JS "doğru" alfa tuşuna sayısal tuşlarla aynı davranır:>const arr = ['a', 'b'] >arr.test = 'hello' >arr 0: "a" 1: "b" test: "hello" length: 2
johny neden

5

Bireysel karakterlerden oluşan bir dizi elde edebilirsiniz.

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

ve sonra düzenli Javascript kullanarak döngü, ya da jQuery tarafından dizenin karakterleri üzerinde yineleme yapabilirsiniz

var test = "test string";

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

5

bu dizeyi kullanarak bir karakter dizisine dönüştürebilir split()ve ardından yineleyebilirsiniz.

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

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


görünüşe göre bu unicode karakterler ve grafik sembolleri ile başarısız.
johny neden

4

Bir karakter düzeyinde metinde bir dönüşüm yapmak ve dönüştürülen metni sonunda geri almak istiyorsanız, şöyle bir şey yaparsınız:

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

Yani adımlar:

  • Dizeyi bir karakter dizisine (liste) bölme
  • Her karakteri bir işlev aracıyla eşleme
  • Sonuçta elde edilen karakter dizisini sonuçta elde edilen dizeye birleştirin

0

Bugünün JavaScript'inde şunları yapabilirsiniz:

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

Açıkçası, c + c c ile yapmak istediğiniz her şeyi temsil eder.

Bu geri döner

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


Muhtemelen:[...'This is my string'].map((c)=>c+c)
Alan

0

Bu , eski tarayıcılarda ve 💩 gibi UTF-16 karakterleriyle çalışmalıdır.

Bu en uyumlu çözüm olmalıdır. Ancak, bir fordöngüden daha az performans gösterir .

Normal ifadeyi kullanarak normal ifadeyi oluşturdum

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

Bu yardımcı olur umarım!


"Daha az perfomant" ile ne demek istiyorsun? Bence bu gereksinime daha uygun olduğu ve iyi performans gösterdiği için "daha yavaş" demek istediniz.
hippietrail

-1

Sen olabilir tek karakterlere erişmek ile str.charAt(index)veya str[index]. Ancak ikinci yol ECMAScript'in bir parçası değildir, bu yüzden öncekiyle daha iyi gitmelisiniz.


Bundan uzak dururum. Ne yazık ki bu IE'nin tüm sürümlerinde çalışmaz. Güven Bana. Zor yoldan öğrendim.
Xavi

3
ECMAScript'in bir parçasıdır, ancak yalnızca yeni çıkan 5. baskıda 3. değil.
kanguru

-1

Her karakteri canlandırmak istiyorsanız, span öğesine kaydırmanız gerekebilir;

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

Bence bunu yapmanın en iyi yolu, daha sonra açıklıkları işlemek. (örneğin TweenMax ile)

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


-1

Bu kodu deneyin

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