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?

Tom Select の fuzzy 検索は「CD」と「CD」を区別しない?全角・半角が混在する日本語でも快適に使えた話

0
Posted at

🏁 はじめに

多くの選択肢から検索・選択できる UI として人気のある Tom Select
今回はその fuzzy検索(曖昧検索) を使っていて、思いがけず便利な挙動に気づいたのでシェアします。

キーワードはズバリ…

全角と半角の「CD」は区別されない?

日本語環境でありがちな“全角・半角混在問題”。
その悩みを軽減してくれるかもしれない、Tom Select × Fuse.js の組み合わせに注目です。


🔧 使用ライブラリ

  • Tom Select v2.2.2
    CDN:

    <script src="https://cdn.jsdelivr.net/npm/tom-select@2.2.2/dist/js/tom-select.complete.min.js"></script>
    
  • Fuse.js(内部で使用)
    Tom Select の fuzzy検索 はこのライブラリに依存しています。


🧪 検証内容:全角・半角でどうなる?

以下のように「全角CD」「半角CD」が混在したリストを Tom Select に表示し、
fuzzy検索で 「CD」(半角) を入力したときの挙動を確認しました。

🔹 HTMLコード(抜粋)

<select id="fuzzySelect">
  <option value="1509">ABザクタンクCD01</option>
  <option value="1510">ABザクタンクCD02</option>
  <option value="1511">ABザクタンクCD03</option>
  <option value="1512">ABザクタンクCD04</option>
</select>

🔹 JavaScript(Tom Select 初期化)

new TomSelect("#fuzzySelect", {
  maxItems: 1,
  allowEmptyOption: true,
  placeholder: "あいまい検索で探す",
  onInitialize: function() {
    this.clear();
  }
});

🔹 ソースコード全体

サンプルコードはここを見てください
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Tom Select - 前方一致 & あいまい検索</title>
  <link href="https://cdn.jsdelivr.net/npm/tom-select@2.2.2/dist/css/tom-select.css" rel="stylesheet">
  <style>
    body { font-family: sans-serif; margin: 2em; }
    label { font-weight: bold; display: block; margin-top: 1.5em; }
    select { width: 100%; max-width: 400px; }
  </style>
</head>
<body>
  <h2>Tom Select 検索タイプ別サンプル(初期未選択)</h2>

  <!-- ▼ 前方一致検索(ドライバー) -->
  <label for="prefixSelect">🚚 前方一致検索(パイロット)</label>
  <select id="prefixSelect" placeholder="前方一致で検索">
    <option value="" disabled selected hidden>-- 選択してください --</option>
    <option value="80">123455970 連邦一郎</option>
    <option value="81">123452482 ティターンズ太郎</option>
    <option value="82">123455157 連邦二郎</option>
    <option value="83">123455796 ティターンズ三平</option>
    <option value="1117">123453000 テストパイロット</option>
    <option value="1133">Zeon0101 ジオン一郎</option>
    <option value="1134">Zeon0102 ジオン二郎</option>
    <option value="1135">Zeon0103 ジオン三郎</option>
    <option value="1136">Zeon0104 ジオン四郎</option>
    <option value="1137">Zeon0105 ジオン五郎</option>
  </select>

  <!-- ▼ あいまい検索(車両) -->
  <label for="fuzzySelect">🚗 あいまい検索(モビルスーツ)</label>
  <select id="fuzzySelect" placeholder="あいまい検索で探す">
    <option value="" disabled selected hidden>-- 選択してください --</option>
    <option value="73">グフ99901</option>
    <option value="74">グフ99902</option>
    <option value="75">グフ99903</option>
    <option value="76">グフ99904</option>
    <option value="413">ABガンタンクCD</option>
    <option value="1509">ABザクタンクCD01</option>
    <option value="1510">ABザクタンクCD02</option>
    <option value="1511">ABザクタンクCD03</option>
    <option value="1512">ABザクタンクCD04</option>
    <option value="1513">ABザクタンクCD05</option>
  </select>

  <script src="https://cdn.jsdelivr.net/npm/tom-select@2.2.2/dist/js/tom-select.complete.min.js"></script>
  <script>
    // ▼ 前方一致検索(ドライバー)
    new TomSelect("#prefixSelect", {
      maxItems: 1,
      placeholder: "前方一致で検索",
      allowEmptyOption: true,
      score: function(search) {
        return function(item) {
          const label = item.text.toLowerCase();
          const keyword = search.toLowerCase();
          return label.startsWith(keyword) ? 1 : 0;
        };
      },
      onInitialize: function() {
        this.clear();
      }
    });

    // ▼ あいまい検索(車両)
    new TomSelect("#fuzzySelect", {
      maxItems: 1,
      allowEmptyOption: true,
      placeholder: "あいまい検索で探す",
      onInitialize: function() {
        this.clear();
      }
    });
  </script>
</body>
</html>

📷 実際の動作結果

半角「CD」と入力すると、全角「CD」を含む項目もヒットしてくれました!

えっ、Fuse.js って全角と半角を区別するんじゃないの?

と思って調べてみたら…


🤔 全角・半角の区別について調べてみた

✔ Fuse.js は原則として「全角と半角を区別」する

Fuse.js 単体で以下のような比較を行った場合、 "CD""CD" は別物扱いになります。

const list = [{ name: "ABCD" }, { name: "ABCD" }];
const fuse = new Fuse(list, { keys: ["name"] });

fuse.search("CD"); // 全角「CD」はヒットしない

🧠 仮説

じゃあなぜ Tom Select でヒットしたのか…?

💡 推測される理由

  • threshold の設定(ゆるめ)によって、多少の違いは曖昧一致として許容されている
  • Unicode正規化は明示的にされていないが、視覚的に近い文字列を「近い」と評価している可能性
  • Fuse.js の includeScore によるスコア判定が「類似」と判断

✅ まとめ

比較内容 結果 補足
半角「CD」 vs 全角「CD」 ✅ ヒット Tom Select + Fuse.js の fuzzy検索はスコア的に「近い」と判断
明示的な normalize() ❌ 使用していない それでもヒットしている点が面白い
ユーザー体験的には? 🟢 優しい! 日本語混在環境でも安心して使える!

📝 おわりに

今回のように「ちょっと不思議な挙動」に出会ったとき、
それを試して調べて、推測するって…やっぱり楽しいですね!

「Tom Select の fuzzy 検索って全角・半角にもけっこう寛容だな」と感じたので、
日本語UIの改善や、ユーザーの入力ミスを吸収したい場面ではぜひ活用してみてください!

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?