Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
7
Help us understand the problem. What is going on with this article?
@sugasaki

異体字同一視検索を実装メモ

More than 3 years have passed since last update.

環境

C#、Linq to Entity、SQL Serverです。

はじめに

以下を参考にさせていただきました。(感謝)
karak 異体字同一視検索

異体字とは

標準の字体と同じ意味・発音を持つが、表記に差異がある文字のこと。手書きによる個人差から生じたもの、新字・旧字(簡体・繁体)の違いによるものがある。

目的

峰さん、嶺さん、峯さん、いっぱいいますね。
いざ検索しようとして、みねってどんな字だったっけ?全然ヒットしない!
という事もあろうかと思います。
同様に浜さん、濱さん、濵さん、なかなか検索ヒットできません。

さらにたとえば濵嵜(はまざき)さんという人を検索したい場合、なかなか変換ではでてこないですし、ひらがなも、はまざき・はまさき どっちだったけ?となりがちです。

という時に、「浜」でも「濱」「濵」さんが検索ヒットできるように異体字を同一視して検索できるように実装しました。

異体字辞書の作成

まずは異体字の辞書を用意しました。
DB化するか悩んだのですが、漢字であるしほぼ変わらないであろうことからコードに書いてます。
具体的には以下のような感じです。

var variants = new List<KeyValuePair<string, string>>()
{
    new KeyValuePair<string, string>("濱", "濱|頻|濵|浜|滨"),
    new KeyValuePair<string, string>("浜", "浜|濵|濱"),
    new KeyValuePair<string, string>("領", "領|阾|袊|嶺|岭|领"),
    new KeyValuePair<string, string>("岭", "岭|領|岺|嶺"),
    new KeyValuePair<string, string>("嶺", "嶺|領|岭"),
    ...
}

検索用文字列の変換

浜で検索した場合に正規表現で検索したいので、
浜→[浜|濵|濱]と変換します。

たとえば濵嵜(はまざき)さんという人を検索したい場合は検索ワードとしては以下で正規表現で検索するといい感じになりそうです。
[浜|濵|濱][崎|隑|陭|徛|﨑|㟢|碕|埼|嵜]

浜崎 → [浜|濵|濱][崎|隑|陭|徛|﨑|㟢|碕|埼|嵜] という変換は文字列を1文字ずつ先ほどの辞書を元に変換します。


        public static string get(string word)
        {
            var result = "";

            //異体字一覧(辞書)を取得する
            var vari = Dictionaly.GetDictionaly();

            //文字列を1文字ずつに分割して処理する
            foreach (char c in word)
            {
                //文字が異体字リストにあれば、異体字を取得する。
                //ex. 浜 →  [浜|濵|濱]
                var f = vari.FirstOrDefault(x => x.Key == c.ToString());

                //[]で囲む
                if (f.Key != null)
                {
                    result += "[" + f.Value + "]";
                }
                else
                {
                    result += c;
                }

            }

            //結果を返す
            return result;
        }

検索

Linq to Entityに投げ込みます。

Linq to Entityでは正規表現をそのまま検索できないので、SqlFunctionsを使います。
SqlFunctionsはSystem.Data.Objects.SqlClientにあります。

using System.Data.Objects.SqlClient;

//regStringsが検索ワード([浜|濵|濱][崎|隑|陭|徛|﨑|㟢|碕|埼|嵜])等
var query = from c in db.Entity
    where SqlFunctions.PatIndex("%" + regStrings + "%", c.Modid) == 1
    select c;

参考

異体字データベース

Linq to Entityでの正規表現について(stackoverflow)

他にも検索の幅を増やしたい場合には、LinqKit等を使えばより柔軟になりそうです。

7
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
sugasaki
個人的なメモが多いです。 書いてる事は個人の見解であり所属する組織の公式見解ではありません
runners
スポーツで世界を良くしたいエンジニアチーム。応援navi、.finisher、run&といった製品開発をしています!

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
7
Help us understand the problem. What is going on with this article?