Bagaimana saya bisa memproses setiap huruf teks menggunakan Javascript?


363

Saya ingin memberi tahu setiap individu string, tetapi saya tidak yakin bagaimana melakukan ini.

Jadi, jika saya punya:

var str = 'This is my string';

Saya ingin secara terpisah dapat mengingatkan T, h, i, s, dll. Ini hanyalah awal dari ide yang sedang saya kerjakan, tetapi saya perlu tahu bagaimana memproses setiap huruf secara terpisah.

Saya ingin menggunakan jQuery dan berpikir saya mungkin perlu menggunakan fungsi split setelah menguji berapa panjang string.

Ide ide?


3
Mungkin Anda sedang mencari ini: pada ES6, ada for(const c of str) { ... }. Lebih dari itu lebih jauh di bawah ini dalam jawaban yang cukup terperinci tetapi tidak cukup terangkat. PS: @ Tautan ARJUN tidak berfungsi untuk saya.
Maks.

Jawaban:


421

Jika urutan peringatan penting, gunakan ini:

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

Jika urutan peringatan tidak masalah, gunakan ini:

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


2
menggunakan []untuk mendapatkan arang dalam posisi tertentu tidak didukung di IE <9
vsync

13
seperti yang tercakup dalam jawaban lain, Anda bisa menggunakan str.charAt (i) sebagai ganti dari []. untuk lebih lanjut tentang mengapa Anda harus menggunakan charAt vs [], lihat string.charAt (x) atau string [x]
Julian Soro

12
Saya merasa sulit untuk percaya bahwa setiap kompiler JS modern akan menghitung ulang panjangnya jika string belum dimodifikasi di dalam loop. Dalam setiap bahasa lain saya akan dengan senang hati melakukan pemeriksaan panjang pada klausa tes for for loop, dengan asumsi kompiler tahu yang terbaik dan akan mengoptimalkannya sesuai.
Echelon

3
@ Dalmar: Javascript tidak menggunakan UTF-8, ia menggunakan UTF-16 (atau UCS-2, tergantung pada browser). Setiap karakter tunggal dapat direpresentasikan sebagai UTF-8 atau UTF-16 tetapi tidak memiliki masalah ini. Satu-satunya yang memiliki masalah adalah orang-orang yang membutuhkan empat byte di UTF-16 daripada dua byte. πŸ’© adalah karakter yang membutuhkan empat byte di UTF-16. Istilah kunci untuk mencari info lebih lanjut adalah "pesawat astral", "non-BMP", dan "pasangan pengganti".
hippietrail

1
@ Dalmar: Java dan Javascript keduanya memiliki kesamaan UTF-16 (sebelumnya UCS-). Platform utama ketiga yang menggunakannya adalah Windows. Protokol unix, MacOS, dan internet menggunakan UTF-8. charAttersisa dari UCS-2 hari ketika tidak ada pasangan pengganti dan untuk mengatasi masalah fungsi baru, codepointAtditambahkan ke JavaScript yang menangani tumpukan kotoran ramah kita dengan benar. Saya percaya Java juga memilikinya.
hippietrail

240

Mungkin lebih dari selesai. Hanya ingin berkontribusi dengan solusi sederhana lain:

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
contoh terakhir bisa saja[...text].forEach(console.log)
Govind Rai

10
Tidak, tidak bisa. forEach()melewati indeks dan array sebagai argumen kedua dan ketiga. Saya lebih suka tidak mencatatnya ..
Tn. Goferito

1
Perhatikan bahwa operator spread (contoh pertama) dan panggilan split (contoh terakhir) akan membuat array baru. Ini biasanya tidak akan menjadi masalah, tetapi bisa mahal untuk string besar atau sering digunakan.
Randolpho

Bagaimana denganfor (let c of [...text]) { console.log(c) }
Flimm

Dengan itu Anda membuat array baru dari string. Saya tidak melihat manfaatnya. let c of textsudah melakukan pekerjaan.
Tn. Goferito

73

Salah satu solusi yang mungkin dalam javascript murni:

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

Mungkin akan lebih baik dengan var x = 0 dan var c = str.charAt (x).
Kaya

2
Juga, str.length harus disimpan dalam variabel sehingga tidak harus terus diakses.
Eli Gray

8
@ EliGrey Apakah benar-benar penting untuk menempatkan panjang dalam variabel? Apakah Anda memiliki tolok ukur saat ini lebih disukai daripada memiliki lebih sedikit garis kode?
pm_labs

@ paul_sns Menariknya, tampaknya ada perbedaan kecil , setidaknya di Edge (perbedaan 0,7 ms untuk array elemen 10.000): jsfiddle.net/carcigenicate/v8vvjoc1/1 . Mungkin bukan tes yang sempurna, tapi ini berdasarkan rata-rata 10.000 tes.
Carcigenicate

1
@paul_sns Juga menarik, Chrome melakukan tes yang sama sekitar 2% dari waktu (~ 5ms vs ~ 0,0997ms), dan kedua versi memberikan waktu yang sama, sehingga sepertinya Edge tidak dioptimalkan.
Carcigenicate

69

Cara memproses setiap huruf teks (dengan tolok ukur)

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

untuk

Klasik dan sejauh ini yang paling berkinerja . Anda harus menggunakan yang ini jika Anda berencana menggunakannya dalam algoritme kinerja kritis, atau yang memerlukan kompatibilitas maksimum dengan versi browser.

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

untuk ... dari

untuk ... dari adalah ES6 baru untuk iterator. Didukung oleh sebagian besar browser modern. Ini secara visual lebih menarik dan kurang rentan terhadap kesalahan pengetikan. Jika Anda ingin yang ini dalam aplikasi produksi, Anda mungkin harus menggunakan transpiler seperti Babel .

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

untuk setiap

Pendekatan fungsional . Airbnb disetujui . Kelemahan terbesar dari melakukannya dengan cara ini adalah split(), yang menciptakan array baru untuk menyimpan setiap huruf dari string.

Mengapa? Ini menegakkan aturan abadi kita. Berurusan dengan fungsi murni yang mengembalikan nilai lebih mudah untuk dipertimbangkan daripada efek samping.

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

atau

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

Berikut ini adalah yang saya sukai.

untuk ... di

Tidak seperti untuk ... dari, Anda mendapatkan indeks surat daripada surat itu. Itu berkinerja sangat buruk.

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

peta

Pendekatan fungsi, mana yang baik. Namun, peta tidak dimaksudkan untuk digunakan untuk itu. Ini harus digunakan ketika perlu mengubah nilai-nilai di dalam array, yang tidak terjadi.

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

atau

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

1
Pada mesin saya, forloop klasik sebenarnya adalah yang paling lambat kedua, sedangkan for...ofyang tercepat (sekitar tiga kali lebih cepat for).
John Montgomery

1
Dimana patokannya? Apa solusi tercepat?
poitroae

1
@johnywhy Itu dua tahun lalu dan tautannya sudah mati jadi saya tidak yakin bagaimana Anda mengharapkan saya untuk mempertahankan hasil yang saya dapatkan saat itu. Menyiapkan patokan baru sekarang setuju dengan kesimpulan zurfyx, dengan forloop menjadi sedikit lebih cepat.
John Montgomery

1
@JohnMontgomery Saya tidak berharap Anda melakukan apa pun. Hanya catatan untuk pembaca masa depan bahwa hasil Anda berbeda dari jawabannya. Saya pribadi ingin tahu hasil mana yang berlaku untuk browser hari ini 2020, meskipun '2018 belum lama berselang. Tautan mana yang mati?
Johnny mengapa

1
@johnywhy Tautan di atas dengan semua tes yang sebenarnya mengembalikan 404 untuk saya.
John Montgomery

42

Sebagian besar jika tidak semua jawaban di sini salah karena mereka akan putus setiap kali ada karakter dalam string di luar Unicode BMP (Basic Multilingual Plane) . Itu artinya semua Emoji akan rusak .

JavaScript menggunakan UTF- 16 Unicode untuk semua string. Dalam UTF-16, karakter di luar BMP dibuat dari dua bagian, yang disebut " Pasangan Pengganti " dan sebagian besar jawaban di sini akan memproses setiap bagian dari pasangan demikian secara individual alih-alih sebagai karakter tunggal.

Salah satu cara dalam JavaScript modern sejak setidaknya 2016 adalah dengan menggunakan iterator String baru . Inilah contoh (hampir) langsung dari 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"


4
Untuk solusi modern untuk memisahkan string menjadi karakter sambil mempertimbangkan pasangan pengganti akun, lihat: stackoverflow.com/a/42596897/527702
hippietrail

20

Anda bisa mencoba ini

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

11
Masih merupakan pilihan, tetapi bukan pemain. Jangan letakkan jQuery di mana-mana.
cagatay

10

Satu lagi solusi ...

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

3
Jika Anda hanya menginginkan char dan bukan indeks, akan lebih cepat menggunakan for..ofloopfor (let ch of t) { alert(ch) }
Shaheen Ghiassy

10

Ketika saya perlu menulis kode pendek atau satu baris, saya menggunakan "retasan" ini:

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

Ini tidak akan menghitung baris baru sehingga bisa menjadi hal yang baik atau buruk. Jika Anda ingin memasukkan baris baru, ganti: /./dengan /[\S\s]/. Satu-liner lain yang mungkin Anda lihat mungkin menggunakan .split()yang memiliki banyak masalah


jawaban Terbaik. Mempertimbangkan masalah dengan unicode dan juga dapat digunakan dengan konstruksi fungsional dengan .map () dll.
rofrol

Satu-satunya hal yang saya tidak suka tentang ini adalah ketika saya ingin akses ke params tambahan diteruskan ke fungsi forEachpanggilan vs params yang dikirimreplace . Jika saya tahu saya ASCIIing, saya pikir saya masih memiliki beberapa kasus penggunaan split. Jawaban yang bagus!
ruffin

Jawaban ini memiliki bonus dengan memilih sebelumnya nilai yang akan Anda periksa
Fuzzyma

1
Saya pikir ini tidak akan memperhitungkan masalah Unicode kecuali jika ada ubendera bersama dengan gbendera? OK baru saja diuji dan saya benar.
hippietrail

9

JS baru memungkinkan ini:

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

8

Lebih baik menggunakan for ... pernyataan, jika string berisi karakter unicode, karena ukuran byte yang berbeda.

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

7

jawaban singkat: Array.from(string)akan memberi Anda apa yang mungkin Anda inginkan dan kemudian Anda dapat beralih di atasnya atau apa pun karena itu hanya sebuah array.

ok mari kita coba dengan string ini: abc|⚫️\nβšͺ️|πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘§.

codepoint adalah:

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

jadi beberapa karakter memiliki satu codepoint (byte) dan beberapa memiliki dua atau lebih, dan baris baru ditambahkan untuk pengujian tambahan.

jadi setelah pengujian ada dua cara:

  • byte per byte (codepoint per codepoint)
  • grup karakter (tetapi tidak seluruh emoji keluarga)

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

Anda sekarang dapat mengulangi setiap titik kode Unicode yang terkandung dalam sebuah String dengan menggunakan String.prototype[@@iterator], yang mengembalikan nilai tipe Simbol yang terkenal Symbol.iterator- iterator default untuk Objek mirip array ( Stringdalam kasus ini).

Kode contoh:

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.

Ini berfungsi dengan karakter Unicode seperti emoji atau karakter non-roman yang akan menyandung konstruksi lama.

Referensi: Tautan MDN ke String.prototype @@ iterator .


2
Perhatikan bahwa Anda dapat melakukan ini dengan cara yang lebih pendek dengan for ... ofloop juga di atas string - yaitu gula sintaks untuk mengakses iterator.
Aditya MP

6

Anda sekarang dapat menggunakan di kunci.

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


Menggunakan di adalah praktik yang buruk dan mengerikan ketika tanpa filter saya sangat menyarankan ini
Downgoat

4
@Downgoat mengapa? Apa yang buruk tentang itu? Maksud saya jika saya berada dalam situasi di mana saya tahu bahwa 'in' didukung oleh mesin Javascript saya, dan bahwa kode saya tidak akan menemukan jalannya ke mesin lain ... mengapa tidak menggunakannya?
TKoL

@TKoL Lihat ini .
Alan

@Lan inadalah bagian sah dari bahasa tersebut. Gunakan segala sesuatu dengan tepat. Artikel Anda memperingatkan bahwa inmenafsirkan kunci alfa sama dengan kunci numerik. Begitu? Mungkin itu yang Anda inginkan. Dapat juga dikatakan bahwa metode lain salah mengabaikan kunci alpha. Imo, ofmemiliki perilaku yang benar. Dalam array JS, elemen tanpa kunci alfa masih memiliki kunci: yang numerik. Di konsol saya, JS "benar" memperlakukan kunci alfa sama dengan tombol numerik:>const arr = ['a', 'b'] >arr.test = 'hello' >arr 0: "a" 1: "b" test: "hello" length: 2
Johnny mengapa

5

Anda bisa mendapatkan berbagai karakter individual seperti itu

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

dan kemudian loop menggunakan Javascript biasa, atau Anda dapat mengulangi karakter string menggunakan jQuery oleh

var test = "test string";

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

5

Anda dapat mengubah string ini menjadi array menggunakan karakter split(), lalu beralih melalui itu.

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

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


ternyata ini gagal dengan karakter unicode dan simbol grafik.
Johnny mengapa

4

Jika Anda ingin melakukan transformasi pada teks pada tingkat karakter, dan mendapatkan teks yang diubah kembali di akhir, Anda akan melakukan sesuatu seperti ini:

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

Jadi langkah-langkahnya:

  • Pisahkan string menjadi array (daftar) karakter
  • Petakan setiap karakter melalui sebuah functor
  • Gabungkan array karakter yang dihasilkan bersama-sama ke dalam string yang dihasilkan

0

Di JavaScript hari ini, Anda bisa

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

Jelas, c + c mewakili apa pun yang ingin Anda lakukan dengan c.

Ini kembali

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


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

0

Ini seharusnya berfungsi di browser lama dan dengan karakter UTF-16 seperti πŸ’©.

Ini harus menjadi solusi yang paling kompatibel. Namun, performanya kurang dari afor loop.

Saya menghasilkan ekspresi reguler menggunakan 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)
});

Semoga ini membantu!


Apa yang Anda maksud dengan "kurang perfomant"? Saya pikir maksud Anda lebih lambat karena lebih sesuai dengan persyaratan dan berkinerja baik.
hippietrail

-1

Anda dapat mengakses satu karakter dengan str.charAt(index)atau str[index]. Namun cara yang terakhir ini bukan bagian dari ECMAScript sehingga Anda sebaiknya menggunakan yang sebelumnya.


Saya akan menjauh dari itu. Sayangnya itu tidak berfungsi di semua versi IE. Percayalah kepadaku. Saya mempelajarinya dengan cara yang sulit.
Xavi

3
Ini adalah bagian dari ECMAScript, tetapi hanya di edisi ke-5 yang baru dirilis, bukan ke-3.
kangax

-1

Jika Anda ingin menghidupkan setiap karakter Anda mungkin perlu membungkusnya dalam elemen span;

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

Saya pikir ini adalah cara terbaik untuk melakukannya, kemudian memproses bentang. (misalnya dengan TweenMax)

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


-1

Coba kode ini

    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>
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.