JavaScriptを使用してテキストの各文字をどのように処理できますか?


362

文字列の個々の文字に警告したいのですが、これを行う方法がわかりません。

だから、私が持っているなら:

var str = 'This is my string';

T、h、i、sなどを個別にアラートできるようにしたいと思います。これは私が取り組んでいるアイデアのほんの始まりに過ぎませんが、各文字を個別に処理する方法を知る必要があります。

jQueryを使用したいのですが、文字列の長さをテストした後、split関数を使用する必要があるかもしれないと考えていました。

アイデア?


3
たぶんあなたはこれを探していました:ES6現在、がありfor(const c of str) { ... }ます。その詳細については、以下で詳しく説明しますが、十分に賛成されていません。PS:@ARJUNのリンクが機能しません。
最大

回答:


421

アラートの順序が重要な場合は、これを使用します。

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

アラートの順序が重要でない場合は、これを使用します。

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


2
[]特定の位置にある文字を取得するためのtheの使用は、IE <9ではサポートされていません
vsync

13
他の回答で説明されているように、[]の代わりにstr.charAt(i)を使用できます。charAt vs []を使用する理由の詳細については、string.charAt(x)またはstring [x]を
Julian Soro

12
ループ内で文字列が変更されていない場合、最新のJSコンパイラーが長さを再計算するとは思えません。他のすべての言語では、forループのテスト句で長さのチェックを喜んで行います。コンパイラーが最善を知っており、それに応じて最適化するものと想定しています。
エシェロン2014

3
@Dagmar:JavaScriptはUTF-8を使用せず、UTF-16(またはブラウザーによってはUCS-2)を使用します。すべての1文字はUTF-8またはUTF-16のいずれかで表すことができますが、この問題はありません。問題があるのは、UTF-16で2バイトではなく4バイトが必要なものだけです。💩は、UTF-16で4バイトを必要とする文字です。詳細情報を調べるための主要な用語は、「アストラルプレーン」、「非BMP」、および「サロゲートペア」です。
ヒッピートレイル2018

1
@Dagmar:JavaとJavaScriptはどちらも共通のUTF-16(以前のUCS-)を持っています。それを使用する3番目の主要なプラットフォームはWindowsです。Unix、MacOS、およびインターネットプロトコルはUTF-8を使用します。charAtサロゲートペアがなく、問題に対処するためのUCS-2の日から残っています。新しい機能codepointAtがJavaScriptに追加され、フレンドリーなプーの山を正しく処理します。Javaにもあると思います。
ヒッピートレイル2018

240

それはおそらく解決された以上のものです。別のシンプルなソリューションで貢献したいだけです:

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
最後の例は単純に[...text].forEach(console.log)
Govind Rai

10
いいえ、できません。forEach()インデックスと配列を2番目と3番目の引数として渡します。私はそれをログに記録し
たく

1
スプレッド演算子(最初の例)とsplit呼び出し(最後の例)の両方が新しい配列を作成することに注意してください。これは通常問題にはなりませんが、大きな文字列や頻繁な使用にはコストがかかる可能性があります。
Randolpho

どうですかfor (let c of [...text]) { console.log(c) }
Flimm

これで、文字列から新しい配列を作成します。メリットがわかりません。let c of textすでに仕事をしています。
Goferito氏、19年

73

純粋なJavaScriptで可能な解決策の1つ:

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

おそらく、var x = 0およびvar c = str.charAt(x)の方が適しています。
リッチ

2
また、str.lengthは変数に格納する必要があるため、アクセスし続ける必要はありません。
Eli Gray、

8
@EliGrey変数に長さを入れることは本当に重要ですか?コードの行数を減らすよりも望ましいベンチマークはありますか?
pm_labs 2013

@paul_sns興味深いことに、少なくともEdge(10000要素の配列では0.7ミリ秒の差)には小さな違いがあるようです:jsfiddle.net/carcigenicate/v8vvjoc1/1。おそらく完璧なテストではありませんが、それは平均10000テストに基づいています。
発癌性物質2016年

1
@paul_snsまた興味深いことに、Chromeは約2%の時間(〜5ms vs〜0.0997ms)で同じテストを行い、両方のバージョンが同じ時間を示したため、Edgeは最適化されていないようです。
発がん性物質2016年

69

テキストの各文字を処理する方法(ベンチマーク付き)

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

ために

クラシックで、最もパフォーマンス高いものです。パフォーマンスが重要なアルゴリズムでの使用を計画している場合、またはブラウザーのバージョンとの最大の互換性が必要な場合は、これを使用する必要があります。

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

for ... ofは、イテレータ用の新しいES6です。最近のほとんどのブラウザでサポートされています。見た目がより魅力的で、タイプミスをしにくくなります。これを本番アプリケーションで使用する場合は、おそらくBabelのようなトランスパイラーを使用する必要があります。

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

forEach

機能的アプローチ。Airbnb承認。この方法でこれを行う最大の欠点split()は、文字列の個々の文字を格納する新しい配列を作成するです。

どうして?これにより、不変のルールが適用されます。値を返す純粋な関数を扱う方が、副作用よりも簡単に推論できます。

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

または

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

以下は嫌いなものです。

のために...

for ... ofとは異なり、文字ではなく文字のインデックスを取得します。それはかなり悪いパフォーマンスをします。

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

地図

機能アプローチ、これは良いことです。ただし、マップはそのために使用するためのものではありません。配列内の値を変更する必要がある場合に使用する必要がありますが、そうではありません。

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

または

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

1
私のマシンでは、クラシックforループが2番目に遅く、実際for...ofには最速でした(約3倍の速さfor)。
ジョンモンゴメリー

1
ベンチマークはどこですか?最速のソリューションは何ですか?
poitroae

1
@johnywhyそれは2年前のことで、リンクが切れているので、私が戻ってきた結果をどのように防御することが期待できるかわかりません。新しいベンチマークを設定すると、zurfyxの結論に同意するようになりましたが、forループはわずかに高速です。
ジョンモンゴメリー

1
@JohnMontgomery私はあなたが何もすることを期待していません。あなたの結果が答えとは異なるという将来の読者への単なるメモ。私は個人的に、どの結果が今日2020のブラウザーに当てはまるのか知りたいのですが、altho '2018はそれほど昔ではありませんでした。どのリンクが死んでいますか?
ジョニーなぜ

1
@johnywhy実際のすべてのテストの上部にあるリンクは、404を返します。
ジョンモンゴメリー

42

Unicode BMP(Basic Multilingual Plane)の外側の文字列に文字がある場合はいつでも壊れるので、ここでの回答のすべてではないにしてもほとんどが間違っています。つまり、すべての絵文字が壊れます。

JavaScriptはすべての文字列にUTF- 16 Unicodeを使用します。UTF-16では、BMPを超える文字は「サロゲート ペア」と呼ばれる2つの部分から構成され、ここでの回答のほとんどは、そのようなペアの各部分を単一の文字としてではなく個別に処理します。

少なくとも2016年以降の最新のJavaScriptの1つの方法は、新しい文字列イテレータを使用することです。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
サロゲートペアを考慮しながら文字列を文字に分割する最新のソリューションについては、stackoverflow.com
a / 42596897/527702

20

あなたはこれを試すことができます

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

11
まだオプションですが、パフォーマンスは高くありません。jQueryをどこにも配置しないでください。
cagatay 2017年

10

もう1つの解決策...

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

3
charのみが必要で、インデックスは必要ない場合は、for..ofループを使用する方が高速ですfor (let ch of t) { alert(ch) }
Shaheen Ghiassy

10

短いコードやワンライナーを記述する必要がある場合は、次の「ハック」を使用します。

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

これは改行を数えないため、良いことにも悪いことにもなります。あなたはどの改行を含める場合は、交換してください:/.//[\S\s]/。他のワンライナーは、おそらく使用を見ることが.split()いる多くの問題を抱えています


ベストアンサー。ユニコードの問題を考慮に入れ、.map()などの機能的な構成で使用することもできます
rofrol

これについて私が気に入らないのはforEach呼び出しの関数に渡された追加パラメーターとで送信されreplaceパラメーターにアクセスしたいときだけです。ASCIIを使用していることがわかっている場合は、まだいくつかの使用例があると思いますsplit。すばらしい答えです!
ruffin

この回答には、とにかくチェックする値を事前に選択するというボーナスがあります
Fuzzyma

1
uフラグと一緒にgフラグがない限り、これはUnicodeの問題を考慮に入れないと思いましたか?テストしただけでOKでした。
ヒッピートレイル2017

9

新しいJSはこれを可能にします:

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

8

バイトサイズが異なるため、文字列にUnicode文字が含まれている場合は、for ... ofステートメントを使用することをお勧めします。

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

7

短い答え:Array.from(string)おそらくあなたが望んでいるものを与え、それは単なる配列なのでそれで何でも繰り返すことができます。

では、次の文字列で試してみましょうabc|⚫️\n⚪️|👨‍👩‍👧‍👧

コードポイントは次のとおりです。

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

そのため、一部の文字には1つのコードポイント(バイト)があり、一部には2つ以上のコードポイントがあり、追加のテストのために改行が追加されています。

したがって、テスト後は2つの方法があります。

  • バイトごとのバイト(コードポイントごとのコードポイント)
  • 文字グループ(家族全員の絵文字ではない)

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

を使用して、文字列に含まれる個々のUnicodeコードポイントを反復処理できるようになりましたString.prototype[@@iterator]。これは、よく知られているシンボルタイプSymbol.iterator(配列のようなオブジェクトのデフォルトの反復子String)(この場合)の値を返します。

コード例:

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.

これは、絵文字やローマ字以外の文字などのレガシー構造をトリップするUnicode文字で機能します。

参照:String.prototype @@ iteratorへのMDNリンク


2
これはfor ... of、文字列に対してループを使用することで、より簡単に行うことができます。これは、イテレータにアクセスするための構文シュガーです。
Aditya MP

6

キーワードで使用できるようになりました

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


inを使用することは悪い習慣であり、フィルタリングされていない場合は恐ろしいです。私はこれに対して強くお勧めします
Downgoat

4
@Downgoatなんで?それの何が悪いのですか?つまり、「in」がJavascriptエンジンでサポートされていることがわかっていて、コードが別のエンジンに到達しないという状況にある場合は、どうしてそれを使用しないのでしょうか。
TKoL 2016年

@TKoL これを見てください。
アラン

@アランinは言語の正当な部分です。物事を適切に使用してください。記事では、inアルファキーを数字キーと同じように解釈するよう注意しています。そう?たぶんそれがあなたの望みです。他の方法では、アルファキーが誤って無視されるとも言えます。イモ、of正しい振る舞いをしています。JS配列では、アルファキーのない要素にもキーがあります。数値キーです。:私のコンソールで、JS「正しく」扱い数字キーと同じアルファキーを>const arr = ['a', 'b'] >arr.test = 'hello' >arr 0: "a" 1: "b" test: "hello" length: 2
ジョニーなぜ

5

あなたはそのように個々の文字の配列を得ることができます

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

通常のJavascriptを使用してループするか、jQueryを使用して文字列の文字を反復することができます。

var test = "test string";

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

5

この文字列をを使用して文字の配列に変換しsplit()、それを反復処理できます。

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

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


明らかにこれはユニコード文字とグラフィックシンボルで失敗します。
ジョニーなぜ

4

文字レベルでテキストの変換を行い、変換されたテキストを最後に戻す場合は、次のようにします。

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

だからステップ:

  • 文字列を文字の配列(リスト)に分割します
  • ファンクターを介して各キャラクターをマッピングする
  • 結果の文字配列を結果の文字列に結合します

0

今日のJavaScriptでは、

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

明らかに、c + cはcで何をしたいかを表します。

これは戻ります

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


おそらく:[...'This is my string'].map((c)=>c+c)
アラン

0

これは古いブラウザで動作し、💩のようなUTF-16文字で動作するはずです。

これが最も互換性のあるソリューションであるはずです。ただし、forループよりもパフォーマンスが低下します。

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

お役に立てれば!


「パフォーマンスが低い」とはどういう意味ですか?要件への適合性が高く、パフォーマンスが高いため、「遅い」という意味です。
ヒッピートレイル

-1

あなたはできる単一の文字にアクセスstr.charAt(index)たりstr[index]。ただし、後者の方法はECMAScriptの一部ではないため、前者の方法を使用することをお勧めします。


私はそれから離れます。残念ながら、これはIEのすべてのバージョンで機能するわけではありません。私を信じて。私はそれを難し​​い方法で学びました。
Xavi、

3
これはECMAScriptの一部ですが、新しくリリースされた第5版のみで、第3版ではありません。
kangax 2009

-1

各キャラクターをアニメートしたい場合は、それをspan要素でラップする必要があるかもしれません。

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

これがそれを行う最良の方法だと私は思います、そしてスパンを処理します。(たとえば、TweenMaxを使用)

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


-1

このコードを試してください

    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>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.