Как классифицировать японские символы как кандзи или кана?

Учитывая текст ниже, как я могу классифицировать каждый символ как кана или кандзи?

誰 か 確認 上 記 こ れ ら の フ

Чтобы получить что-то подобное

誰 - kanji
か - kana
確 - kanji
認 - kanji 
上 - kanji 
記 - kanji 
こ - kana 
れ - kana
ら - kana
の - kana
フ - kana

(Извините, если я сделал это неправильно.)

5 ответов

Решение

Эта функциональность встроена в класс Character.UnicodeBlock. Некоторые примеры блоков Unicode, связанных с японским языком:

Character.UnicodeBlock.of('誰') == CJK_UNIFIED_IDEOGRAPHS
Character.UnicodeBlock.of('か') == HIRAGANA
Character.UnicodeBlock.of('フ') == KATAKANA
Character.UnicodeBlock.of('フ') == HALFWIDTH_AND_FULLWIDTH_FORMS
Character.UnicodeBlock.of('!') == HALFWIDTH_AND_FULLWIDTH_FORMS
Character.UnicodeBlock.of('。') == CJK_SYMBOLS_AND_PUNCTUATION

Но, как всегда, дьявол кроется в деталях:

Character.UnicodeBlock.of('A') == HALFWIDTH_AND_FULLWIDTH_FORMS

где является символом полной ширины. Так что это в той же категории, что и полуширина катакана выше. Обратите внимание, что во всю ширину отличается от нормального (полуширина) A:

Character.UnicodeBlock.of('A') == BASIC_LATIN

Используйте таблицу, подобную этой, чтобы определить, какие значения Unicode используются для катаканы и кандзи, затем вы можете просто привести символ к int и проверить, где он находится, что-то вроде

int val = (int)て;
if (val >= 0x3040 && val <= 0x309f)
  return KATAKANA
..

Кажется, это было бы интересным использованием для класса CharMatcher в Guava. Используя таблицы, связанные в ответе Джека, я создал это:

public class JapaneseCharMatchers {
  public static final CharMatcher HIRAGANA = 
      CharMatcher.inRange((char) 0x3040, (char) 0x309f);

  public static final CharMatcher KATAKANA = 
      CharMatcher.inRange((char) 0x30a0, (char) 0x30ff);

  public static final CharMatcher KANA = HIRAGANA.or(KATAKANA);

  public static final CharMatcher KANJI = 
      CharMatcher.inRange((char) 0x4e00, (char) 0x9faf);

  public static void main(String[] args) {
    test("誰か確認上記これらのフ");
  }

  private static void test(String string) {
    System.out.println(string);
    System.out.println("Hiragana: " + HIRAGANA.retainFrom(string));
    System.out.println("Katakana: " + KATAKANA.retainFrom(string));
    System.out.println("Kana: " + KANA.retainFrom(string));
    System.out.println("Kanji: " + KANJI.retainFrom(string));
  }
}

Запуск этого печатает ожидаемое:

誰 か 確認 上 記 こ れ ら の フ

Хирагана: かこれらの

Катакана: フ

Кана: かこれらのフ

Кандзи: 誰確認上記

Это дает вам большие возможности для работы с японским текстом, определяя правила определения того, находится ли персонаж в одной из этих групп в объекте, который может не только выполнять много полезных задач сам по себе, но также может использоваться с другими API-интерфейсами. такие как гуава Splitter учебный класс.

Редактировать:

Основываясь на ответе jleedev, вы также можете написать такой метод:

public static CharMatcher inUnicodeBlock(final Character.UnicodeBlock block) {
  return new CharMatcher() {
    public boolean matches(char c) {
      return Character.UnicodeBlock.of(c) == block;
    }
  };
}

и используйте это как:

CharMatcher HIRAGANA = inUnicodeBlock(Character.UnicodeBlock.HIRAGANA);

Я думаю, что это может быть немного медленнее, чем в другой версии.

Вам нужно получить ссылку, которая дает отдельные диапазоны для символов кана и кандзи. Из того, что я видел, алфавиты и эквиваленты обычно получают блок символов.

Я знаю, что вы не просили VBA, но вот вариант VBA для тех, кто хочет знать:

Вот функция, которая сделает это. Это разобьет предложение, как у вас выше, в одну ячейку. Возможно, вам придется добавить некоторые проверки ошибок, как вы хотите обрабатывать разрывы строк или английские символы и т. Д., Но это должно быть хорошим началом.

Function KanjiKanaBreakdown(ByVal text As String) As String

Application.ScreenUpdating = False
Dim kanjiCode As Long
Dim result As String
Dim i As Long

For i = 1 To Len(text)
    If Asc(Mid$(text, i, 1)) > -30562 And Asc(Mid$(text, i, 1)) < -950 Then
        result = (result & (Mid$(text, i, 1)) & (" - kanji") & vbLf)
    Else
        result = (result & (Mid$(text, i, 1)) & (" - kana") & vbLf)
    End If
Next

KanjiKanaBreakdown = result
Application.ScreenUpdating = True

End Function
Другие вопросы по тегам