split() は、文字列を区切り文字で分けて配列にします。
元の文字列は変わりません。
example.js
const csv = 'りんご,みかん,ぶどう';
console.log(csv.split(','));
console.log(csv);
出力書き換えて実行できます
[ 'りんご', 'みかん', 'ぶどう' ]
りんご,みかん,ぶどう
example.js
console.log('りんご,みかん'.split(','));
console.log('りんご'.split(','));
console.log('りんご'.split());
console.log('りんご'.split(''));
出力書き換えて実行できます
[ 'りんご', 'みかん' ]
[ 'りんご' ]
[ 'りんご' ]
[ 'り', 'ん', 'ご' ]
上のコードは書き換えて実行できます。区切りを ',' から 'ん' にしてみてください。
何が返るのか
| 渡すもの |
結果 |
| 区切り文字がある |
区切って並べた配列 |
| 区切り文字が見つからない |
元の文字列1つだけが入った配列 |
空文字 '' |
1文字ずつ(絵文字は壊れる) |
| 何も渡さない |
元の文字列1つだけが入った配列 |
example.js
console.log(''.split(','));
console.log(''.split(',').length);
console.log(''.split(''));
console.log(''.split('').length);
出力書き換えて実行できます
[ '' ]
1
[]
0
example.js
const input = '';
console.log(input.split(',').length);
console.log(input.split(',').filter(s => s !== '').length);
出力書き換えて実行できます
1
0
見つからなくても空配列にはなりません。 必ず1件以上返ります。
length === 1 かどうかで「区切りがあったか」を判定できます。
空文字列を分けると空文字が返る
''.split(',') は空配列ではありません。空文字が1つ入った配列です。
javascript
const text = 'あ🙂い';
console.log(text.length);
console.log(text.split('').length);
console.log(text.split('').map(c => c.codePointAt(0).toString(16)));
4
4
[ '3042', 'd83d', 'de42', '3044' ]
example.js
const text = 'あ🙂い';
console.log([...text]);
console.log(Array.from(text));
console.log(text.length, [...text].length);
出力書き換えて実行できます
[ 'あ', '🙂', 'い' ]
[ 'あ', '🙂', 'い' ]
4 3
''.split(',') は [ '' ] で長さ1、''.split('') は [] で長さ0。
区切りが空文字のときだけ、特別に空配列になります。
未入力を件数で数えると1件あると誤解します。
example.js
const flag = '🇯🇵';
console.log([...flag]);
console.log([...flag].length);
console.log(flag.length);
出力書き換えて実行できます
[ '🇯', '🇵' ]
2
4
example.js
const seg = new Intl.Segmenter('ja', { granularity: 'grapheme' });
console.log([...seg.segment('あ🙂🇯🇵い')].map(s => s.segment));
出力書き換えて実行できます
[ 'あ', '🙂', '🇯🇵', 'い' ]
絵文字が壊れる
split('') は16ビット単位で切ります。絵文字や一部の漢字は
2つの単位(サロゲートペア)でできているので、半分に割れます。
中身をコードポイント(16進数)で見ると、何が起きているか分かります。
example.js
const text = 'a,,b,';
console.log(text.split(','));
console.log(text.split(',').length);
出力書き換えて実行できます
[ 'a', '', 'b', '' ]
4
example.js
const text = 'a,,b, ,c';
console.log(text.split(',').filter(s => s.trim() !== ''));
出力書き換えて実行できます
[ 'a', 'b', 'c' ]
人が数えると3文字ですが、length は4です。
3042 … あ
d83d と de42 … 🙂 を2つに割ったもの
3044 … い
d800〜dfff の範囲は単独では文字にならない半分です。
片方だけ取り出しても、元の絵文字には戻せません。
直しかた
スプレッド構文か Array.from() を使います。どちらも文字の単位で区切ります。
example.js
const text = 'a,b,c,d';
console.log(text.split(',', 2));
console.log(text.split(',', 0));
出力書き換えて実行できます
[ 'a', 'b' ]
[]
javascript
const line = 'key: value: extra';
console.log(line.split(': ', 2));
[ 'key', 'value' ]
length は4のままですが、[...text].length は3です。
文字数を数えたいときは length を使わないでください。
それでも足りない場合があります。 国旗や肌の色つきの絵文字は、
複数の文字が組み合わさって1つに見えています。
example.js
const line = 'key: value: extra';
const i = line.indexOf(': ');
console.log([line.slice(0, i), line.slice(i + 2)]);
出力書き換えて実行できます
[ 'key', 'value: extra' ]
example.js
const text = 'a b\tc\nd';
console.log(text.split(' '));
console.log(text.split(/\s+/));
出力書き換えて実行できます
[ 'a', '', 'b\tc\nd' ]
[ 'a', 'b', 'c', 'd' ]
見た目どおりに数えるには Intl.Segmenter を使います(書記素の単位)。
example.js
const text = 'a1b2c';
console.log(text.split(/\d/));
console.log(text.split(/(\d)/));
出力書き換えて実行できます
[ 'a', 'b', 'c' ]
[ 'a', '1', 'b', '2', 'c' ]
example.js
console.log('a1b2c'.split(/(?:\d)/));
出力書き換えて実行できます
[ 'a', 'b', 'c' ]
Intl.Segmenter は Node 16 / Chrome 87 / Safari 14.1 以降で使えます。
連続した区切りは空文字になる
区切りが並んでいると、その間に空文字が入ります。
example.js
const parts = ['a', 'b', 'c'];
console.log(parts.join());
console.log(parts.join('-'));
console.log(parts.join(''));
出力書き換えて実行できます
a,b,c
a-b-c
abc
example.js
console.log([1, null, 2, undefined, 3].join('-'));
出力書き換えて実行できます
1--2--3
末尾の , の後ろも1件として数えられています。
空の項目を捨てたいなら、自分で落としてください。
example.js
const text = ' apple \n banana \n\n cherry ';
const lines = text
.split('\n')
.map(s => s.trim())
.filter(s => s !== '');
console.log(lines);
console.log(lines.join(' / '));
出力書き換えて実行できます
[ 'apple', 'banana', 'cherry' ]
apple / banana / cherry
件数を制限する
第2引数で、返す件数の上限を指定できます。
残りは捨てられます。 「最初の1つとそれ以外」に分けたいときには使えません。
extra が消えました。こういうときは位置で切ります。
正規表現で分ける
区切りに正規表現を渡せます。空白の数がばらばらなときに使えます。
丸括弧(キャプチャ)を書くと、区切りそのものも結果に入ります。
区切りを残したくないなら、括弧を (?:…) にします。
戻すときは join
join() が対になります。引数を省くと , で繋がります。
null と undefined は空文字になります。
行に分けて処理し、また繋ぐ形はよく使います。
改行は環境によって \n と \r\n があります。両方に対応するなら split(/\r?\n/) と書きます。
区切らずに置き換えたいだけなら
String.prototype.replace() と replaceAll() を使います。
分けたあとに数えた個数が見た目と合わないときは、符号単位で分けている可能性があります。
→ 文字を正しく数える