Подтвердить что ты не робот

Как можно улучшить этот метод для преобразования имени в правильный случай?

Я пишу основную функцию для преобразования миллионов имен в однократном пакетном процессе из их текущей формы в верхнем регистре в правильный смешанный случай. Я придумал следующую функцию:

public string ConvertToProperNameCase(string input)
{
    char[] chars = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(input.ToLower()).ToCharArray();

    for (int i = 0; i + 1 < chars.Length; i++)
    {
        if ((chars[i].Equals('\'')) ||
            (chars[i].Equals('-')))
        {                    
            chars[i + 1] = Char.ToUpper(chars[i + 1]);
        }
    }
    return new string(chars);
}

Он работает в большинстве случаев, например:

  • ДЖОН СМИТ → Джон Смит
  • SMITH, JOHN T → Смит, Джон Т
  • ДЖОН О'БРИАН → Джон О'Брайан
  • ДЖОН ДУ-СМИТ → Джон Доу-Смит

Есть некоторые случаи краев, которые не работают:

  • JASON MCDONALD → Джейсон Макдональд (Правильно: Джейсон Макдональд)
  • OSCAR DE LA HOYA → Оскар Де Ла Хойя (Правильно: Оскар де ла Хойя)
  • MARIE DIFRANCO → Мари Дифранко (Правильно: Мари ДиФранко)

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

4b9b3361

Ответ 1

Думаю, вы снова запустите стену, потому что, как правило, вы не сможете правильно судить, разумно или нет конверсия.

Рассмотрим случаи вашего края

JASON MCDONALD → Джейсон Макдональд (Правильно: Джейсон Макдональд)

Вы могли бы просто проверить Mc в начале вашего имени, а затем применить исправление, верно? Но что, если ваш человек называется Mcizck (я это сделал, конечно), и это не должно быть исправлено в Mc Izck, но его следует оставить как есть?

Нет идеального решения этой проблемы на 100%. То, что у вас здесь, является проблемой на естественном языке, и их действительно трудно решить, особенно для компьютера. Культуры слишком разные, чтобы их правильно смоделировать. Даже если вы говорите, что североамериканские соглашения имеют приоритет, у вас будет высокий процент "ложных срабатываний". Наше общество состоит из огромного сочетания культур, просто не хватает сказать, что "североамериканцы имеют преимущество".

Без обработки крайних случаев, я думаю, ваше текущее решение будет работать в 99% случаев. Все дальнейшие краевые случаи следует исправить вручную, если действительно требуются 100% правильные имена.

Ответ 2

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

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

Если вы не можете позволить пользователям обновлять свои собственные имена, вторым наиболее надежным методом будет сбор списков (последних) имен из общедоступных источников. Если вы можете найти достаточное количество из них, вы должны уметь покрывать больше случаев краев - просто посмотрите, существует ли имя в вашем правильно обведенном списке, а затем используйте этот корпус.

Ответ 3

Нет общего решения этой проблемы. Даже в общих случаях, таких как "Mc", есть встречные примеры. У меня был друг в колледже с именем "Мак", который не использовал следующий символ; по-видимому, это было связано с иммиграционными поколениями назад, и все они придерживаются исторически неверного написания.

Один из моих первых имен коллег - это два традиционных имени CamelCased. Вы никогда не сможете это объяснить.

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

Ответ 4

Вы можете создавать правила, которые могут приблизить вас, но вы не можете получить 100%. Например, вы можете создать список префиксов (Mc, Di и т.д.)

  • Если префикс заканчивается гласным, а следующая буква - гласным, строчным.
  • Если префикс заканчивается гласной, а следующая буква - согласная, верхняя.
  • Если префикс заканчивается согласным, следующая буква имеет верхний регистр.

Etc... но вы, вероятно, захотите получить хороший список префиксов, и у вас всегда будут исключения.

Ответ 5

Ну, во-первых, этот код генерирует исключение, если имя имеет значение "или" в конце, так как оно попытается извлечь следующий элемент (не существующий) в массиве. edit, см. комментарий ниже

Кроме этого...

Я не думаю, что вы действительно можете объяснить DiFranco, если только вы не учитываете DiFranco и никакой другой Di (есть ли какие-либо?). Кроме того, я думаю, что можно с уверенностью предположить, что любой Mc заслуживает капитала в следующем письме. И я также думаю, что можно с уверенностью сказать, что де и ла, когда пространство вокруг них может быть опущено.

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

Ответ 6

Вы могли

  • Разделите ваши разделители ",", "и" -"
  • Заглавие каждого раздела
  • Обрабатывайте все свои кромки для каждой фразы

Ответ 7

Проблема в том, что, как и все остальные, вы никогда не поймаете каждый крайний случай. Я собирался предложить здесь здесь, загружая полный набор данных и сравнивая их. Но этот набор данных имеет верхний регистр. Поскольку это одноразовый процесс, вместо этого я бы загрузил список из вышеупомянутой ссылки, которая имеет 1000 имен, вручную исправить их и обработать ваши записи против этого списка. Отметьте эти записи, которые не обрабатываются, и посмотрите, достаточно ли их количества, чтобы их можно было управлять вручную.

Ответ 8

Ваш вопрос касается улучшения вашей программы. Мой ответ: "Какое направление - улучшение?" У вас есть два разных случая кромки, которые являются взаимоисключающими. Либо вы не поймаете людей с необычными правилами капитализации, либо вы не поймаете людей, которые не соблюдают необычные правила капитализации.

Я пошел в школу с кем-то с фамилией "Де Ла Роса". Учитывая ваш пример де ла Хойя, было бы справедливо предположить, что "де ла Роса" также является фамилией кого-то там. Поэтому, если вы реализуете один метод декапитализации "де ла", то вы пропустите моего друга, и мне будет грустно. И если вы не реализуете декапитализацию, вы пропустите других людей. И не дай бог, чтобы вы столкнулись с некоторыми де ла Росой, которых не поймали ни один из методов...

Итак, подумайте, какое направление вы считаете "улучшением" для своего кода? Если вы считаете, что вам следует обрабатывать крайние случаи для необычной капитализации и вручную учитывать тех, кто не соблюдает, другие предоставленные ответы помогут вам в достижении этой цели. Если вы считаете, что вам следует вручную обрабатывать необычную капитализацию, тогда ваш код не нуждается в изменении. В любом случае вам придется вручную что-то делать.

Ответ 9

<System.Runtime.CompilerServices.Extension()> _
Public Function ProperCase(ByVal value As String) As String

    If String.IsNullOrWhiteSpace(value) Then
        Return String.Empty
    End If

    value = value.Trim

    Dim sb As New StringBuilder(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(value.ToLower))

    '// Special cases ' and -
    For i As Integer = 0 To sb.Length
        Dim c As Char = sb(i)
        If sb(i).Equals("'") Or sb(i).Equals("-") Then
            'Upper Case Next character
            sb(i + 1) = Char.ToUpper(sb(i + 1))
        End If
    Next

    If sb.ToString.StartsWith("Mac") Then
        sb(3) = Char.ToUpper(sb(3))
    End If

    If sb.ToString.StartsWith("Mc") Then
        sb(2) = Char.ToUpper(sb(2))
    End If

    Return sb.ToString

End Function