LoginSignup
11
8

More than 5 years have passed since last update.

Go - ひらがな・カタカナの相互変換

Posted at

tl;dr

  • ひらがなとカタカナは Unicode で 96 文字ずつある
  • ひらがなとカタカナの Unicode 符号位置は 96 文字ずれている
  • ひらがなの rune に 96 を足せばカタカナになる
  • カタカナの rune に 96 を引けばひらがなになる
  • rune がひらがなかどうかは unicode.In(r, unicode.Hiragana) で判定できる
  • rune がカタカナかどうかは unicode.In(r, unicode.Katakana) で判定できる

ひらがなとカタカナの Unicode 符号位置

http://www.unicodemap.org/range/62/Hiragana/http://www.unicodemap.org/range/63/Katakana/ が見やすい。
それぞれ 0x3041 と 0x30a1 からはじまる。

実装コード

HiraganaToKatakana 関数は文字列中のひらがなをカタカナに変換して返す。
KatakanaToHiragana 関数は文字列中のカタカナをひらがなに変換して返す。

package kana

import (
    "unicode"
)

const (
    // http://www.unicodemap.org/range/62/Hiragana/
    hiraganaLo = 0x3041 // ぁ

    // http://www.unicodemap.org/range/63/Katakana/
    katakanaLo = 0x30a1 // ァ

    codeDiff = katakanaLo - hiraganaLo
)

// HiraganaToKatakana はひらがなをカタカナに変換する。
func HiraganaToKatakana(str string) string {
    src := []rune(str)
    dst := make([]rune, len(src))
    for i, r := range src {
        switch {
        case unicode.In(r, unicode.Hiragana):
            dst[i] = r + codeDiff
        default:
            dst[i] = r
        }
    }
    return string(dst)
}

// KatakanaToHiragana はカタカナをひらがなに変換する。
func KatakanaToHiragana(str string) string {
    src := []rune(str)
    dst := make([]rune, len(src))
    for i, r := range src {
        switch {
        case unicode.In(r, unicode.Katakana):
            dst[i] = r - codeDiff
        default:
            dst[i] = r
        }
    }
    return string(dst)
}

テストコード

package kana_test

import (
    "testing"

    "path/to/kana"
)

func TestHiraganaToKatakana(t *testing.T) {
    tests := []struct {
        input string
        want  string
    }{
        {
            input: "",
            want:  "",
        },
        {
            input: "あいうえお",
            want:  "アイウエオ",
        },
        {
            input: "アイウエオ",
            want:  "アイウエオ",
        },
        {
            input: "あいウえお",
            want:  "アイウエオ",
        },
        {
            input: "あいuえお",
            want:  "アイuエオ",
        },
        {
            input: "あいUえお",
            want:  "アイUエオ",
        },
        {
            input: "あい雨えお",
            want:  "アイ雨エオ",
        },
    }

    for i, test := range tests {
        got := kana.HiraganaToKatakana(test.input)
        if got != test.want {
            t.Errorf("[%d] got %s, but want %s", i, got, test.want)
        }
    }
}

func TestKatakanaToHiragana(t *testing.T) {
    tests := []struct {
        input string
        want  string
    }{
        {
            input: "",
            want:  "",
        },
        {
            input: "アイウエオ",
            want:  "あいうえお",
        },
        {
            input: "あいうえお",
            want:  "あいうえお",
        },
        {
            input: "アイうエオ",
            want:  "あいうえお",
        },
        {
            input: "アイuエオ",
            want:  "あいuえお",
        },
        {
            input: "アイUエオ",
            want:  "あいUえお",
        },
        {
            input: "アイ雨エオ",
            want:  "あい雨えお",
        },
    }

    for i, test := range tests {
        got := kana.KatakanaToHiragana(test.input)
        if got != test.want {
            t.Errorf("[%d] got %s, but want %s", i, got, test.want)
        }
    }
}
11
8
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
11
8