0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

日本語の文章を split(/\\s+/) で数えたら、2,160字が「1単語」になった。読了時間は文字数で出す

0
Posted at

背景

自分のサイトに、文章を貼ると読み終わるまでの目安の時間を出すツールを置いています。
ブログ記事の冒頭に「約3分で読めます」と書きたくて、毎回なんとなくで書いていたのが気持ち悪かったので作りました。
作るときに、英語向けの「1分あたり◯単語」の計算をそのまま日本語に当てたら、ほぼ0秒になりました…。
その理由と、どう数えればいいかの備忘録です。

結論

空白で区切って単語を数える方法は、日本語では使えません。
日本語の文には単語の間に空白が無いので、段落まるごとが1単語になります。
日本語の読了時間は、文字数で数えるのが手堅いです。
どうしても単語で数えたいなら、Intl.Segmenter を使います。

ツールの計算

ツールでは、テキストエリアの中身 t を受け取って、下記のように数えています。
mode は「文字/分」と「単語/分」の切り替え、speed はその速さで、既定は 500文字/分 と 250単語/分 にしています(この既定値は私が決めた目安です)。

// t: テキストエリアに貼られた文章
var chars = Array.from(t).length;          // 文字数(サロゲートペアも1文字)
var trimmed = t.trim();
var words = trimmed === '' ? 0 : trimmed.split(/\s+/).length;  // 空白区切りの単語数
var amount = mode === 'cpm' ? chars : words;
var seconds = Math.round(amount / speed * 60);

Array.from(t) は、文字列を1文字ずつの配列にする書き方だ。
t.length だと絵文字などが2と数えられるので、こちらを使っています。
split(/\s+/) は、空白・改行・タブが1つ以上続くところで区切る、という意味です。

実際に数えてみた

下記の日本語と英語で、文字数と単語数を出してみました(Node.js v24.11.1)。

今日は良い天気なので、近所の公園まで散歩に行きました。
I went for a walk to the park because the weather was nice today.

結果は下記です。

日本語: chars 27, words 1
英語:   chars 65, words 14

英語は14単語と、見たとおりの数になっています。
日本語は27文字あるのに、単語は1つです。
空白が1つも無いので、split しても文全体が1要素のまま残ります。

この文を80回つなげた2,160字の文章でも、単語数は1のままでした。
そのため 250単語/分 で計算すると、読了時間は「0分0秒」になります。
同じ文章を 500文字/分 で計算すると「4分19秒」でした。

Intl.Segmenter で単語に分ける

Intl.Segmenter は、文字列を言語の規則に合わせて「文字」「単語」「文」に分割する、JavaScript の標準の仕組みだ。
仕様は下記にあります。
https://tc39.es/ecma402/#segmenter-objects

下記のように、granularity: 'word' を指定して、単語らしい部分(isWordLike が true のもの)だけを数えます。
句読点や空白は isWordLike が false になるので、自動で除かれます。

const s = '今日は良い天気なので、近所の公園まで散歩に行きました。';
const seg = new Intl.Segmenter('ja', { granularity: 'word' });
const words = [...seg.segment(s)].filter(x => x.isWordLike);
console.log(words.length);
console.log(words.map(x => x.segment).join('|'));

出力は下記になりました。

14
今日|は|良い|天気|なので|近所|の|公園|まで|散歩|に|行き|ま|した

日本語でも、それっぽい単位で14個に分かれているのがわかると思います。
「行き|ま|した」のように、人が思う区切りとは少し違うところもあります。
2,160字の文章だと1,120単語になり、250単語/分 で「4分29秒」でした。
文字数で出した 4分19秒 と、だいたい近い値です。

それでもツールを文字数にしている理由

Intl.Segmenter の分け方は、ブラウザが持っている辞書(ICU という国際化ライブラリ)に依存します。
なので、同じ文章でもブラウザや版によって単語数が変わる可能性がある、と思っています。
読了時間はもともと目安なので、どこで数えても同じになる文字数のほうが、扱いやすい気がします。
単語に分けた結果は、助詞の「は」や「の」も1単語に数えるので、英語の単語数と同じ感覚で読めるわけでもありません。

作ったツールはここに置いています。
https://hashitosystem.com/tools/readtime/

日本語の読了時間を出すなら、空白区切りの単語数ではなく、Array.from(s).length の文字数で計算します。


本記事はAI補助で執筆した、個人開発の紹介記事です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?