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

Mcdonalds to ProperCase в С#

Как бы вы преобразовали имена в правильный регистр в С#?

У меня есть список имен, которые я хотел бы подтвердить.

Например: mcdonalds to McDonalds или o'brien to O'Brien.

4b9b3361

Ответ 1

Нет абсолютно никакого способа, чтобы компьютер просто знал, что первый "D" в "Макдональдс" должен быть капитализирован. Итак, я думаю, что есть два варианта.

  • У кого-то там может быть часть программного обеспечения или библиотека, которая сделает это за вас.

  • Запрет на то, что ваш единственный выбор заключается в следующем: во-первых, я бы поискал имя в словаре слов, имеющих "интересную" капитализацию. Очевидно, вам придется предоставить этот словарь самостоятельно, если он уже не существует. Во-вторых, примените алгоритм, который исправляет некоторые из очевидных, такие как кельтские имена, начинающиеся с O 'и Mac и Mc, хотя при наличии достаточно большого пула имен такой алгоритм, несомненно, будет иметь множество ложных срабатываний. И наконец, запишите первую букву каждого имени, которая не соответствует первым двум критериям.

Ответ 2

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

Ответ 3

Я написал следующие методы расширения. Не стесняйтесь использовать их.

public static class StringExtensions
{
  public static string ToProperCase( this string original )
  {
    if( original.IsNullOrEmpty() )
      return original;

    string result = _properNameRx.Replace( original.ToLower( CultureInfo.CurrentCulture ), HandleWord );
    return result;
  }

  public static string WordToProperCase( this string word )
  {
    if( word.IsNullOrEmpty() )
      return word;

    if( word.Length > 1 )
      return Char.ToUpper( word[0], CultureInfo.CurrentCulture ) + word.Substring( 1 );

    return word.ToUpper( CultureInfo.CurrentCulture );
  }

  private static readonly Regex _properNameRx = new Regex( @"\b(\w+)\b" );

  private static readonly string[] _prefixes = { "mc" };

  private static string HandleWord( Match m )
  {
    string word = m.Groups[1].Value;

    foreach( string prefix in _prefixes )
    {
      if( word.StartsWith( prefix, StringComparison.CurrentCultureIgnoreCase ) )
        return prefix.WordToProperCase() + word.Substring( prefix.Length ).WordToProperCase();
    }

    return word.WordToProperCase();
  }
}

Ответ 4

Это интересная проблема. Я не думаю, что есть решение "из коробки".

Я добавил в закладки следующую статью, которая может быть близка к тому, что вы хотите:

Потерянный и найденный идентификатор Правильный поставщик форматов форматов (реализация IFormatProvider)

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

Ответ 5

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

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

Идеальное решение - использовать людей для исправления данных.

Ответ 6

Для этого требуется, чтобы ваша программа могла интерпретировать английский язык в определенной степени. По крайней мере, можно разбить строку на множество слов. В .NET Framework нет API-интерфейса, который может достичь этого.

Однако, если бы это было возможно, вы могли бы использовать следующий код.

public string ProperCase(string str, Func<string,bool> isWord) {
  var word = new StringBuilder();
  var cur = new StringBuilder();
  for ( var i = 0; i < str.Length; i++ ) {
    cur.Append(cur.Length == 0 ? Char.ToUpper(str[i]) : str[i]));
    if ( isWord(cur.ToString()) {
      word.Append(cur.ToString());
      cur.Length = 0;
    }
  }
  if ( cur.Length > 0 ) {
    word.Append(cur);
  }
  return word.ToString();
}

Это не идеальное решение, но оно дает вам общее представление о схеме

Ответ 7

Вы можете проверить фамилию нижнего/смешанного случая на словарь (файл), в котором есть правильные оболочки, а затем вернуть "реальное" значение из словаря.

У меня был быстрый google, чтобы узнать, существует ли он, но безрезультатно!

Ответ 8

CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
TextInfo textInfo = cultureInfo.TextInfo;
string txt = textInfo.ToTitleCase("texthere");

Ответ 9

Я планирую написать такую ​​функцию, но, вероятно, не перейду к слишком большому количеству случаев... Ниже в psuedo-коде с регулярным выражением для сопоставления...

начните с /\ b [A-Z] +\b/в соответствии с установленным соответствием, поэтому каждая последовательность букв по границе слова совпадает с набором.

if the string is all uppercase...
  lower-case the string
  upper-case the first letter
  do the following beginning of string replacements
    Vanb -> VanB
    Vanh -> VanH
    Mc? -> Mc?  (uppercase wildcard character)
    Mac[^kh] -> Mac? (uppercase wildcard match)

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

"De La " -> "de la "

Это должно уловить большинство случаев для имен в частности... но хорошая база данных с общими именами будет очень приятной.

Ответ 10

Вот мое решение. Это жестко закодирует имена в программе, но с небольшой работой вы можете сохранить текстовый файл вне программы и прочитать в исключениях имени (т.е. Van, Mc, Mac) и пройти через них.

public static String toProperName(String name)
{
    if (name != null)
    {
        if (name.Length >= 2 && name.ToLower().Substring(0, 2) == "mc")  // Changes mcdonald to "McDonald"
            return "Mc" + Regex.Replace(name.ToLower().Substring(2), @"\b[a-z]", m => m.Value.ToUpper());

        if (name.Length >= 3 && name.ToLower().Substring(0, 3) == "van")  // Changes vanwinkle to "VanWinkle"
            return "Van" + Regex.Replace(name.ToLower().Substring(3), @"\b[a-z]", m => m.Value.ToUpper());

        return Regex.Replace(name.ToLower(), @"\b[a-z]", m => m.Value.ToUpper());  // Changes to title case but also fixes 
                                                                                   // appostrophes like O'HARE or o'hare to O'Hare
    }

    return "";
}