名前の表記がブレる?そもそもの解決方法とは?

名前の表記がブレる?そもそもの解決方法とは?

この記事の要点

  1. 01人の目には同じ名前でも、全角と半角、大文字と小文字、記号の有無が違うだけで、コンピューターは別のものとして扱います。
  2. 02表記のゆれは入力した人のミスよりも、手入力した名前で相手を特定しようとする仕組みの側に問題があります。
  3. 03根本的な解決は、相手ごとにユニークIDを振り、名前ではなくIDで紐付けて管理することです。
  4. 04IDを振れないデータは、比べる前に文字列を同じルールで整える「正規化」で対応しますが、これは次善策です。
  5. 05正規化で吸収できない例外は、名前とIDの対応表を一か所にまとめて管理します。
目次
  1. 表記のゆれとは何か
  2. なぜ、ゆれは起きるのか
  3. 習いたての頃に経験した、売上0円の事例
  4. 解決方法①:ユニークIDを振って、IDで紐付ける(基本)
  5. なぜ、名前ではなくIDなのか
  6. IDを振るときのポイント
  7. 解決方法②:IDを振れない場合は、比べる前に文字列を整える(正規化)
  8. 解決方法③:それでも吸えない例外は、対応表にまとめる
  9. まとめ

売上を取引先ごとに集計したら、ある取引先だけ金額が0円になっていた。画面で見ると名前は同じなのに、なぜか一致しない。こうした問題の多くは、目に見えない「表記のゆれ」が原因です。この記事では、ゆれが起きる原因と、根本的な解決方法である「ユニークIDで管理する」考え方、そしてIDを振れない場合の対処を紹介します。

表記のゆれとは何か

人の目には同じに見えても、コンピューターは1文字でも違えば「別のもの」として扱います。たとえば次のような違いです。

見た目は同じでも違うもの例
全角スペースと半角スペース「Blue Moon」と「Blue Moon」
全角英数字と半角英数字「ABC123」と「ABC123」
大文字と小文字「Moon Books」と「Moon books」
記号の有無「sora.shop」と「sorashop」
前後の見えない空白「GOIT」と「GOIT 」
略称と正式名称「Blue Moon」と「Blue Moon Books」

※ 表の名前は、説明のための架空の例です。

なぜ、ゆれは起きるのか

原因は、プログラムよりも「入力の仕方」にあることがほとんどです。

  • 同じ名前を、複数の人が手で入力している
  • 同じ名前を、別々のシステムやシートで管理している
  • 外部のサービスから取り込んだデータと、自社で作った一覧の書き方が違う
  • コピー&ペーストで、見えない空白が一緒に入り込む

入力した人もタイミングも違えば、ゆれは自然に生まれます。誰かのミスというより、手入力した名前で相手を特定しようとする仕組みの側に問題があります。

習いたての頃に経験した、売上0円の事例

プログラミングを習いたての頃、棚を貸し出しているお店の売上を、出店者ごとに集計する仕組みを作ったことがあります。出店者の一覧のシートと売上の明細のシートを、「屋号(お店の名前)」で突き合わせて合計を出す仕組みでした。

ところが、一部の出店者だけ売上が0円になっていました。調べてみると、2つのシートで屋号の書き方がわずかに違っていました。英語の屋号の大文字と小文字、単語の間のスペース、屋号の途中のピリオドの有無などです。売上の明細は別のシステムから取り込んでいたため、入力した人もタイミングも違っていました。

最初は「全角と半角の違いだろう」と考えました。しかし実際には、それだけではありませんでした。ゆれの種類は1つではなく、直しても別のゆれが見つかります。当時の私は、ゆれを1つずつ吸収する処理を足し続けました。

あとから振り返ると、本当の原因は別のところにありました。名前という、ゆれるものを使って、相手を特定していたことです。

出店者一覧と売上明細で、同じ屋号の表記がわずかに違っている例
見た目は同じでも、スペース・大文字小文字・記号の違いで一致しない

解決方法①:ユニークIDを振って、IDで紐付ける(基本)

根本的な解決は、名前ではなくユニークIDで紐付けて管理することです。ユニークIDとは、1つの相手に1つだけ振る、他と重ならない番号や記号のことです。

たとえば出店者に「S001」「S002」のようなIDを振り、出店者の一覧にも、売上の明細にも、このIDを持たせます。集計はIDで突き合わせます。名前は、人が見て分かるようにするための「表示用の項目」にとどめます。

名前で突き合わせる方法と、IDで突き合わせる方法を比べた図
名前ではなくIDで突き合わせれば、表記のゆれが起きても集計はずれない

なぜ、名前ではなくIDなのか

  • 名前はゆれる:全角・半角、大文字・小文字、記号の有無など、書き方は人や場面によって変わります。IDは機械的に振るので、ゆれません。
  • 名前は変わる:社名の変更、屋号の変更、改称は普通に起こります。名前で紐付けていると、名前が変わった瞬間に過去のデータとつながらなくなります。IDは、名前が変わっても変わりません。
  • 名前は重なる:同じ名前の別の相手がいることもあります。IDなら区別できます。

IDを振るときのポイント

  • 重複させない:同じIDを2つの相手に振らない。1つの相手に複数のIDも振らない
  • 一度振ったら変えない:名前が変わっても、IDはそのままにする
  • 意味を持たせすぎない:「東京の飲食店の3番目」のように意味を詰め込むと、状況が変わったときに困る。連番など、単純なものがよい
  • IDを振る場所を1つにする:新しい相手を登録するときは、一覧に追加してIDを発行する。各所でバラバラに作らない
  • 取り込むデータにも、同じIDを持たせる:別のシステムから取り込むデータには、そのシステム側にもこのIDを入力してもらう

解決方法②:IDを振れない場合は、比べる前に文字列を整える(正規化)

外部のサービスから取り込むデータなど、自分たちではIDを振れない場合もあります。その場合の次善策が「正規化」です。比べる前に、両方の文字列を同じルールで整えます。

  • 全角の英数字やスペースを、半角にそろえる
  • 前後の空白や、不要な記号を取り除く
  • 大文字と小文字をそろえる

スプレッドシートやExcelなら、TRIM(前後の空白を除く)、LOWER(小文字にそろえる)、SUBSTITUTE(記号を取り除く)といった関数の組み合わせで実現できます。プログラムで処理するなら、たとえば次のように書けます(JavaScriptの例)。

// 比べるための文字列に整える関数
function normalizeForCompare(str) {
  if (!str) return '';
  return str.toString()
    .normalize('NFKC')          // 全角英数字・全角スペースを半角にそろえる
    .replace(/[\s.・]/g, '')    // スペース、ピリオド、中黒を取り除く
    .toLowerCase();             // 大文字を小文字にそろえる
}

normalize('NFKC') は、Unicodeで定められた正規化の方法の1つです。全角の英数字やスペースを、対応する半角の文字にそろえます。

解決方法③:それでも吸えない例外は、対応表にまとめる

同じ相手が、片方では短い名前、もう片方では地名入りの正式名で登録されている場合は、正規化しても一致しません。こうした例外は、「この名前は、このIDの相手」という対応表にまとめます。

// 表記が大きく違う名前は、ここで同じIDにひも付ける
const NAME_TO_ID = {
  'bluemoon': 'S001',
  'bluemoonbooks': 'S001',
};

対応表を使う場合も、最終的には名前ではなくIDで集計します。

まとめ

名前が一致しないときは、目に見えない表記のゆれを疑います。そして、根本的には「名前で相手を特定している」ことを疑ってください。

  • 全角と半角、大文字と小文字、記号の有無、前後の空白など、ゆれの種類は1つではありません。
  • 基本は、ユニークIDを振って、IDで紐付けて管理します。名前は表示用にとどめます。
  • IDを振れないデータは、正規化で文字列を整えてから比べます。これは次善策です。
  • 正規化で吸えない例外は、名前とIDの対応表を一か所にまとめて管理します。

集計が合わないときは、まず金額が0になっている行の名前を、1文字ずつ見比べてみてください。そのうえで、「そもそもIDで紐付けられないか」を考えてみましょう。

よくある質問

すでに名前で管理している一覧に、あとからIDを振っても大丈夫ですか。

大丈夫です。一覧にIDの列を足して連番を振り、そのあと明細の側にも同じIDを持たせます。過去の明細は、正規化や対応表を使って一度だけIDを埋めると、以降はIDで集計できます。

スプレッドシートの数式だけで、表記のゆれを吸収できますか。

ある程度はできます。TRIM、LOWER、SUBSTITUTEなどで整えた列を作り、その列で突き合わせます。プログラムと併用する場合は、両方で同じルールにそろえてください。

どの行が一致していないかを、まとめて見つける方法はありますか。

整えた名前の列を両方のシートに作り、COUNTIF関数で相手のシートに存在するかを数えると、0になった行が一致していない名前だと分かります。

カタカナの全角と半角もそろえられますか。

NFKCの正規化では、半角カタカナは全角カタカナにそろいます。ひらがなとカタカナの違いはそろいませんので、必要な場合は別の処理を加えます。

参考資料

  1. String.prototype.normalize()|MDN Web Docs
  2. Unicode Normalization Forms(UAX #15)|Unicode Consortium

この記事をシェア

山本 一成株式会社GOIT 代表取締役

2001年生まれ、21歳で起業、明治大学大学院修了(MBA)。税理士試験官報合格。Flutter/Python歴5年、kintone有資格者。バックオフィス・税理士事務所のDXに強み。業務整理・設計からシステム開発、現場導入まで、中小企業のDXを一気通貫で支援している。