Перечисление строки графемой вместо символа

Строки обычно перечисляются символом. Но, particuarly при работе с Unicode и неанглийскими языками, иногда я должен перечислить строку графемой. Таким образом, объединение меток и диакритических знаков должно быть сохранено с основным символом, который они изменяют. Что лучший способ состоит в том, чтобы сделать это в .NET?

Вариант использования: Считайте отличные фонетические звуки в серии слов IPA.

  1. Упрощенное определение: существуют непосредственные отношения между графемой и звуком.
  2. Реалистическое определение: Специальные "подобные букве" символы должны также быть включены с основным символом (напр. p ʰ), и некоторые звуки может быть представлен двумя символами, к которым присоединяется панель связи (k͡p).

7
задан Dave Mateer 13 January 2010 в 15:05
поделиться

2 ответа

Упрощенный сценарий

TextElementeNumerator очень полезно и эффективно:

private static List<SoundCount> CountSounds(IEnumerable<string> words)
{
    Dictionary<string, SoundCount> soundCounts = new Dictionary<string, SoundCount>();

    foreach (var word in words)
    {
        TextElementEnumerator graphemeEnumerator = StringInfo.GetTextElementEnumerator(word);
        while (graphemeEnumerator.MoveNext())
        {
            string grapheme = graphemeEnumerator.GetTextElement();

            SoundCount count;
            if (!soundCounts.TryGetValue(grapheme, out count))
            {
                count = new SoundCount() { Sound = grapheme };
                soundCounts.Add(grapheme, count);
            }
            count.Count++;
        }
    }

    return new List<SoundCount>(soundCounts.Values);
}

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

private static List<SoundCount> CountSoundsRegex(IEnumerable<string> words)
{
    var soundCounts = new Dictionary<string, SoundCount>();
    var graphemeExpression = new Regex(@"\P{M}\p{M}*");

    foreach (var word in words)
    {
        Match graphemeMatch = graphemeExpression.Match(word);
        while (graphemeMatch.Success)
        {
            string grapheme = graphemeMatch.Value;

            SoundCount count;
            if (!soundCounts.TryGetValue(grapheme, out count))
            {
                count = new SoundCount() { Sound = grapheme };
                soundCounts.Add(grapheme, count);
            }
            count.Count++;

            graphemeMatch = graphemeMatch.NextMatch();
        }
    }

    return new List<SoundCount>(soundCounts.Values);
}

Производительность: В моем тестировании я обнаружил, что TextElementeNumerator был примерно в 4 раза быстрее, чем правильное выражение.

Реалистичный сценарий

К сожалению, нет никакого способа «настроить», как текстовый элемент перечисляет, так что класс не будет использовать в реалистичном сценарии.

Одним из решений - настроить наше регулярное выражение:

[\P{M}\P{Lm}]      # Match a character that is NOT a character intended to be combined with another character or a special character that is used like a letter
(?:                # Start a group for the combining characters:
  (?:                # Start a group for tied characters:
    [\u035C\u0361]      # Match an under- or over- tie bar...
    \P{M}\p{M}*         # ...followed by another grapheme (in the simplified sense)
  )                  # (End the tied characters group)
  |\p{M}             # OR a character intended to be combined with another character
  |\p{Lm}            # OR a special character that is used like a letter
)*                 # Match the combining characters group zero or more times.

Мы, вероятно, также могли бы также создать наш собственный iEnumerator , используя CharunicodeInfo.getUnicoDeCateCateCuteCute English, чтобы восстановить нашему исполнению, но это кажется слишком большой работой для меня и дополнительным кодом для обслуживания. (Кто-нибудь еще хочет пойти?) Регенсы сделаны для этого.

6
ответ дан 7 December 2019 в 07:45
поделиться

Я не уверен, что именно то, что вы ищете, но не ваш вопрос, связанный с нормализацией Unicode?

, когда строка нормализована в форму Unicode C (что является формой по умолчанию), диакритики и Символы, которые они изменяют, объединяются, поэтому, если вы перечисляете символы, которые вы получите базу и символы модификатора вместе.

Когда он нормализуется для формы D, база и символы модификатора разделены и возвращаются отдельно в перечислении.

См. Строка . Спортировать метод для деталей

1
ответ дан 7 December 2019 в 07:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: