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?

JavaScriptで入力候補の表記ゆれを揃える|NFKC正規化・前方一致・重複除外を実装

0
Posted at

kintacoです。自社の重複有無・サジェスト表示プラグインでは、候補比較にNFKC正規化を使っています。この記事では実コードのnormal関数と同じ処理を使い、前方一致・部分一致・正規化後の重複除外に絞って解説します。

サンプルは配列を受け取って候補を返す純粋関数です。kintoneへのAPI照会、入力欄のDOM操作、候補の選択・入力は含みません。製品版にある編集距離による類似候補も省いています。

元の表記と、比較用の文字列を分ける

表示用の値を正規化後の文字列に置き換えるのではなく、比較に使うキーだけを作ります。「ABC 商事」と「abc商事」は同じキーになりますが、候補の表示文字列は最初の値を保持します。

function normal(value) {
  return String(value).normalize('NFKC').toLocaleLowerCase('ja').replace(/\s+/g, '');
}
function suggest(input, items, limit = 5) {
  if (!Number.isInteger(limit) || limit < 1 || limit > 20) {
    throw new Error('limitは1~20の整数にしてください。');
  }
  const term = normal(input);
  if (!term) return [];
  const seen = new Set();
  const ranked = [];
  items.forEach((item, index) => {
    if (typeof item !== 'string') return;
    const key = normal(item);
    if (!key || key === term || seen.has(key)) return;
    const score = key.startsWith(term) ? 0 : key.includes(term) ? 1 : -1;
    if (score < 0) return;
    seen.add(key);
    ranked.push({item, score, index});
  });
  return ranked.sort((a, b) => a.score - b.score || a.index - b.index)
    .slice(0, limit).map(row => row.item);
}

この順番にする理由

空欄は候補検索しません。次に、入力自体と同じ候補は除きます。そのあと前方一致を先、部分一致を後として並べ、同じ比較キーを持つ候補は一度だけ採用します。

候補内にHTMLらしい文字列があっても、この関数は文字列として返すだけです。画面へ表示する場合はtextContentなどを使い、innerHTMLへ未検証の値を流し込まないでください。

NFKCで解決しないこと

NFKCは意味を理解する処理ではありません。「株式会社」と「(株)」、旧社名と新社名、カナの読み、翻訳語を同義語へ変換するわけではありません。また、空白をすべて除くと、業務によっては別の名前を同一候補として扱ってしまいます。空白や大小文字を区別すべき識別子には、そのまま使わないでください。

候補の整理と重複禁止は別の機能

この関数はブラウザーに渡された候補配列しか見ません。候補が出ないことを「同じデータが存在しない」根拠にしてはいけません。API取得件数の上限、閲覧権限、取得後に登録されたデータも考慮します。

保存時の同時登録まで防ぎたい場合には、標準の重複禁止設定などを別途検討します。製品版の重複表示も警告であり、保存を禁止する機能ではありません。

確認する入力例

console.log(suggest('abc', ['ABC商事', 'abc 商事', '東京ABC', 'abc']));
// ['ABC商事', '東京ABC']

正規化・完全一致除外・重複除外・順位・件数制限をNode.jsで確認しました。kintoneの実画面へ組み込んだ動作テストは含みません。日本語IME変換中に照会しない、古い非同期応答を破棄するなどの処理は、UIに接続する段階で必要になります。

設定画面付きの入力支援が必要な場合

自社の重複有無・サジェスト表示プラグインの仕様・設定画面で、設定から利用する方法も紹介しています。サンプルと製品版の対応範囲は異なります。

無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。

参考資料

製品仕様と実コードの確認元:DuplicateSuggest/src/js/core.js(1.0.4)。

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?