Какой правильный алгоритм для определения количества воспринимаемых пользователем символов? - PullRequest
14 голосов
/ 01 февраля 2012

У меня есть задача подсчитать количество воспринимаемых символов на входе.Входные данные представляют собой группу целых (мы можем думать о ней как int[]), которая представляет кодовые точки Unicode.

java.text.BreakIterator.getCharacterInstance () не допускается.(Я имею в виду, что их формула разрешена и это то, что я хотел, но прохождение через их исходный код и таблицы состояний меня ни к чему не привело>. <) </p>

Мне было интересно, каков правильный алгоритм для подсчета количества кластеров графемыучитывая некоторые кодовые точки?

Первоначально , я думал, что все, что мне нужно сделать, это объединить все случаи:

  1. U+0300 – U+036F (комбинация диакритических знаков)

  2. U+1DC0 – U+1DFF (комбинация диакритических знаков)

  3. U+20D0 – U+20FF (комбинация диакритических знаков для символов)

  4. U+FE20 - U+FE2F (объединение половинных отметок)

в предыдущую недиакритическую отметку.

Однако я понял , что перед этой операцией я должен сначала также удалить все не-символы.

Сюда входят:

  1. U+FDD0 - U+FDEF

  2. Последние две кодовые точки каждой плоскости

Но, похоже, есть еще чем заняться. Unicode.org заявляет, что нам нужно включить U+200C (без объединения нулевой ширины) и U+200D (присоединение нулевой ширины) как часть набора продолжающихся символов (источник) .

Кроме того, в нем говорится еще о нескольких вещах, но вся тема рассматривается абстрактно.Например, каковы диапазоны кодовых точек для пробелов, объединяющих метки , символов хангыль джамо, образующих слоги хангыль ?

Кто-нибудь знает правильный алгоритм для подсчета числакластеров графем, которым дано int[] кодовых точек?

1 Ответ

2 голосов
/ 01 февраля 2012

Нет единого канонического метода, подходящего для всех применений, но хорошей отправной точкой является алгоритм Граница кластера графического кода Unicode на странице Unicode.org, на которую вы ссылаетесь.По сути, Unicode предоставляет базу данных для свойства разрыва графемы в каждой кодовой точке, а затем описывает алгоритм, позволяющий определить, разрешен ли разрыв графемы между двумя кодовыми точками на основе назначенных им свойств разрыва графемы.

Вот часть реализации(в C ++) Я некоторое время назад поиграл:

bool BoundaryAllowed(char32_t cp, char32_t cp2) {
  // lbp: left break property; rbp: right break property
  auto lbp = get_property_for_codepoint(cp),
       rbp = get_property_for_codepoint(cp2);

  // Do not break between a CR and LF. Otherwise, break before and after
  // controls.
  if ((CR == lbp && LF == rbp)) {
    // The Unicode grapheme boundary algorithm does not handle LFCR new lines
    return false;
  }

  if (Control == lbp || CR == lbp || LF == lbp || Control == rbp || CR == rbp ||
      LF == rbp) {
    return true;
  }

  // Do not break Hangul syllable sequences.
  if ((L == lbp && (L == rbp || V == rbp || LV == rbp || LVT == rbp)) ||
      ((LV == lbp || V == lbp) && (V == rbp || T == rbp)) ||
      ((LVT == lbp || T == lbp) && (T == rbp))) {
    return false;
  }

  // Do not break before extending characters.
  if (Extend == rbp) {
    return false;
  }

  // Do not break before SpacingMarks, or after Prepend characters.
  if (Prepend == lbp || SpacingMark == rbp) {
    return false;
  }

  return true; // Otherwise, break everywhere.
}

Чтобы получить диапазоны для различных типов кодовых точек, вам просто нужно взглянуть на базу данных символов Unicode.Файл со свойствами разрыва графемы, который описывает их в терминах диапазонов, имеет длину около 1200 строк: http://www.unicode.org/Public/6.1.0/ucd/auxiliary/

Я не совсем уверен, сколько стоит игнорирование не-кодовые знаки, но если это требуется для вашего использования, вы добавите это в свою реализацию.

...