Название соответствующего регистра


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

  • Макдональд
  • Макдугал
  • Смит-Джонс
  • Дэвис второй
  • Георг IV

Следующий код правильно форматирует выше примеров, а также стандартных имен. Пожалуйста, взгляните на мой код и предложить места, где я мог бы сделать его более эффективным. У меня есть идея на этот метод в основном из этой ссылке.

public string ConvertToProperNameCase(string input)
{
    bool SuffixProcessed = false;
    input = input.Trim();

    if (String.IsNullOrEmpty(input))
    {
        return String.Empty;
    }

    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]);
        }
    }

    string s = new string(chars);

    if (((s.ToUpper().StartsWith("MAC") || s.ToUpper().StartsWith("MCC") || s.ToUpper().StartsWith("DE ")) && s.Length > 4))
    {
        try
        {
            s = s.Substring(0, 1).ToUpper() + s.Substring(1, 2).ToLower() + s.Substring(3, 1).ToUpper() + s.Substring(4).ToLower();
        }
        catch
        {
            s = s;
        }
    }

    if ((s.ToUpper().StartsWith("MC")) && s.Length > 3)
    {
        try
        {
            s = s.Substring(0, 1).ToUpper() + s.Substring(1, 1).ToLower() + s.Substring(2, 1).ToUpper() + s.Substring(3).ToLower();
        }
        catch
        {
            s = s;
        }
    }

    if (s.ToUpper().Contains(" III") && !SuffixProcessed)
    {
        try
        {
            s = s.Substring(0, s.ToUpper().IndexOf(" III")) + " " + s.Substring(s.ToUpper().IndexOf(" III"), 4).ToUpper();
            SuffixProcessed = true;
        }
        catch
        {
            s = s;
        }

    }

    if (s.ToUpper().Contains(" II") && !SuffixProcessed)
    {
        try
        {
           s = s.Substring(0, s.ToUpper().IndexOf(" II")) + " " + s.Substring(s.ToUpper().IndexOf(" II"), 3).ToUpper();
           SuffixProcessed = true;
        }
        catch
        {
            s = s;
        }
    }

    if (s.ToUpper().Contains(" IV") && !SuffixProcessed)
    {
        try
        {
            s = s.Substring(0, s.ToUpper().IndexOf(" IV")) + " " + s.Substring(s.ToUpper().IndexOf(" IV"), 3).ToUpper();
            SuffixProcessed = true;
        }
        catch
        {
            s = s;
        }
    }

    return s;
}

После тщательного переваривания пост Уинстон Эверт, вот что я могу с. Этот код теперь будет обрабатывать следующие примеры:

  • Макдональд-Джонс
  • Франк и.
  • Маккарти ХIV
  • МакТавиш-Томас-младший
  • Роберт Робертсон СР

Пересмотренный кодекс

using System;
using System.Windows.Forms;

namespace WindowsFormsApplication5
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string[] Names = new string[]{ "MACDonald-jOnes, FRAnK iV", "MCCarthy xiv", " ", "mcTavish-tOMaS jr", "Robert-ROBERTSON SR."};

            foreach (string s in Names)
                Console.WriteLine(string.Format("Original Name: {0}\n   Converted Name: {1}", s, ConvertToProperNameCase(s)));
        }

        public string ConvertToProperNameCase(string s)
        {
            string ReturnValue = string.Empty;

            if (s.Trim().Length > 0)
            {
                try
                {
                    s = s.ToLower();

                    bool[] Name = new bool[s.Length];
                    for (int i = Name.Length; i < Name.Length; i++)
                    {
                        Name[i] = false;
                    }

                    for (int i = 0; i < s.Length; i++)
                    {
                        if (i == 0)
                        {
                            Name[i] = true;
                        }

                        if (s[i].Equals('\'') || s[i].Equals('-') || s[i].Equals(' '))
                        {
                            Name[i + 1] = true;
                        }
                    }

                    string[] Prefixes = new string[] { "MAC", "MC" };
                    bool[] b = new bool[1] { true };

                    foreach (string p in Prefixes)
                    {
                        if (s.ToUpper().Trim().StartsWith(p))
                        {
                            switch (p.Length)
                            {
                                case 2:
                                    b = new bool[] { true, false, true };
                                    break;
                                case 3:
                                    b = new bool[] { true, false, false, true };
                                    break;
                            }

                            break;
                        }
                    }

                    for (int i = 0; i < b.Length; i++)
                    {
                        Name[i] = b[i];
                    }

                    string[] Suffixes = new string[] { "XXIIII", "IIIII", "VIIII", "XVIII", "XXIII", "IIII", "VIII", "XIII", "XVII", "XXII", 
                                                       "XXIV", "III", "VII", "IIX", "XII", "XIV", "XVI", "XIX", "XXV", "XXI", "II", "IV", "VI", 
                                                       "IX", "XI", "XV", "XX", "I", "V", "X" };

                    foreach (string suf in Suffixes)
                    {
                        if (s.ToUpper().Trim().EndsWith(suf) && (s.Length > (suf.Length + 1)))
                        {
                            for (int i = s.Length - 1; i > (s.Length - (suf.Length + 1)); i--)
                            {
                                Name[i] = true;
                            }

                            break;
                        }
                    }

                    for (int i = 0; i < s.Length; i++)
                    {
                        if (Name[i] == true)
                        {
                            ReturnValue += s.Substring(i, 1).ToUpper();
                        }
                        else
                        {
                            ReturnValue += s.Substring(i, 1);
                        }

                    }

                    return ReturnValue;
                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    return ReturnValue = "Error";
                }
            }
            else
            {
                return ReturnValue = "Empty String";
            }
        }
    }
}


1265
4
c#
задан 7 октября 2011 в 11:10 Источник Поделиться
Комментарии
2 ответа

public string ConvertToProperNameCase(string input)
{
bool SuffixProcessed = false;

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

    input = input.Trim();

if (String.IsNullOrEmpty(input))
{
return String.Empty;
}

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

А название корпуса теперь, почему бы тебе не сделать все строчные здесь, выборочно заглавные кусочки, а затем все TitleCased? Что можно взять все строчные всей этой функция, которая позволит упростить код.

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

string s = new string(chars);

Почему бы вам не создать массив значений, такой же длины, как ваши строки. Изначально все значения установлено значение false. Установите эти значения в true, которые должны быть преобразованы в прописные. Применить uppercasing как последняя часть функции.

    if (((s.ToUpper().StartsWith("MAC") || s.ToUpper().StartsWith("MCC") || s.ToUpper().StartsWith("DE ")) && s.Length > 4))
{
try
{
s = s.Substring(0, 1).ToUpper() + s.Substring(1, 2).ToLower() + s.Substring(3, 1).ToUpper() + s.Substring(4).ToLower();

Было бы намного проще просто установить флаг в массиве should_uppercase значение true.

        }
catch

Не просто поймать любые ошибки. Поймать конкретный тип ошибки, который будет брошен. В противном случае вы можете поймать то, что ты не хотел.

        {
s = s;

Это заявление ничего не делает.

        }
}

if ((s.ToUpper().StartsWith("MC")) && s.Length > 3)
{
try
{
s = s.Substring(0, 1).ToUpper() + s.Substring(1, 1).ToLower() + s.Substring(2, 1).ToUpper() + s.Substring(3).ToLower();
}
catch
{
s = s;
}
}

Вы сделали по сути то же самое дважды. Вы должны положить все эти "Мак, Мак, де, МХК" в массив, а затем перебрать его сделать, чтобы эту логику.

    if (s.ToUpper().Contains(" III") && !SuffixProcessed)

Что, если "третий" появляется где-то, что это не конец? Ты все еще хочешь сделать это?

    {
try
{
s = s.Substring(0, s.ToUpper().IndexOf(" III")) + " " + s.Substring(s.ToUpper().IndexOf(" III"), 4).ToUpper();
SuffixProcessed = true;
}
catch

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

        {
s = s;
}

}

if (s.ToUpper().Contains(" II") && !SuffixProcessed)
{
try
{
s = s.Substring(0, s.ToUpper().IndexOf(" II")) + " " + s.Substring(s.ToUpper().IndexOf(" II"), 3).ToUpper();
SuffixProcessed = true;
}
catch
{
s = s;
}
}

if (s.ToUpper().Contains(" IV") && !SuffixProcessed)
{
try
{
s = s.Substring(0, s.ToUpper().IndexOf(" IV")) + " " + s.Substring(s.ToUpper().IndexOf(" IV"), 3).ToUpper();
SuffixProcessed = true;
}
catch
{
s = s;
}
}

Вы должны по крайней мере поставить эти римские цифры в массив, так что вам не придется дублировать вашу логику. Но что, если Людовик XIV решает использовать вашу систему? Вы могли бы хотеть рассмотреть что-то вроде проверки, действительно ли последнее слово в название состоит только из-Х,я,V, или что-то.

    return s;
}

Раунд 2

    public string ConvertToProperNameCase(string s)
{
string ReturnValue = string.Empty;

Вы не используете аргумент returnvalue до пути позже (кроме парочки мест, где вы не должны использовать его) так переместить его, где вы на самом деле нужно.

        if (s.Trim().Length > 0)

В итоге вы неоднократно тримминг С. Вы можете просто обрезать его сразу и покончить с этим? Вы должны сохранить пробелы на обоих концах?

        {
try
{
s = s.ToLower();

bool[] Name = new bool[s.Length];
for (int i = Name.Length; i < Name.Length; i++)
{
Name[i] = false;
}

Имя не может быть лучшим выбором, потому что переменная не указывает, что он является отслеживание случаев.

                for (int i = 0; i < s.Length; i++)
{
if (i == 0)
{
Name[i] = true;
}

Просто установите имя[0] = истина; перед входом в эту петлю.

                    if (s[i].Equals('\'') || s[i].Equals('-') || s[i].Equals(' '))
{
Name[i + 1] = true;
}
}

string[] Prefixes = new string[] { "MAC", "MC" };
bool[] b = new bool[1] { true };

foreach (string p in Prefixes)
{
if (s.ToUpper().Trim().StartsWith(p))

Ваши строки в строчные. Изменить префиксы так они строчные и вам не нужно ничего прописные.

                    {
switch (p.Length)
{
case 2:
b = new bool[] { true, false, true };
break;
case 3:
b = new bool[] { true, false, false, true };
break;
}

Вы должны быть в состоянии сделать это без перехода на длина. т. е. вы должны быть в состоянии написать код, который работает на все длину.

                        break;
}
}

for (int i = 0; i < b.Length; i++)
{
Name[i] = b[i];
}

А потом писать в другой логический массив, написать прямо на имя[]. В частности, если вы найдете префикс, вы должны установить имя[префикс.длина] = true; в название[0] уже будет правдой.

                string[] Suffixes = new string[] { "XXIIII", "IIIII", "VIIII", "XVIII", "XXIII", "IIII", "VIII", "XIII", "XVII", "XXII", 
"XXIV", "III", "VII", "IIX", "XII", "XIV", "XVI", "XIX", "XXV", "XXI", "II", "IV", "VI",
"IX", "XI", "XV", "XX", "I", "V", "X" };

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

                foreach (string suf in Suffixes)
{
if (s.ToUpper().Trim().EndsWith(suf) && (s.Length > (suf.Length + 1)))

Нет необходимости для родителей вокруг СУФ.Длина+ 1

                    {
for (int i = s.Length - 1; i > (s.Length - (suf.Length + 1)); i--)

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

                        {
Name[i] = true;
}

break;
}
}

for (int i = 0; i < s.Length; i++)
{
if (Name[i] == true)
{
ReturnValue += s.Substring(i, 1).ToUpper();
}
else
{
ReturnValue += s.Substring(i, 1);
}

}

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

                return ReturnValue;
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
return ReturnValue = "Error";

Я рекомендую не включая соответствующую логику GUI в функции такой. Эта функция должна беспокоиться о логике имя и пусть что-то еще беспокоиться об обработке отображения пользовательского интерфейса.

            }
}
else
{
return ReturnValue = "Empty String";

Почему ты присвоении аргумент returnvalue подобное? Нет никакого смысла с returnvalue-это локальная переменная, которая будет выброшена, когда функция заканчивается. Просто вернуть "пустую строку"

        }
}
}

7
ответ дан 8 октября 2011 в 12:10 Источник Поделиться

Помимо сигареты отличные предложения, я бы еще отделить проверки и разбора на отдельные методы. Может быть, даже класс. Извиняюсь за опечатки, как мне пришлось это делать в блокноте, но, надеюсь, основная мысль ниже.

public string ConvertToProperNameCase(string input)
{
input = input.Trim();

if (String.IsNullOrEmpty(input))
{
return String.Empty;
}

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]);
}
}

string s = new string(chars);

const string[] prefixes = { "MAC", " MCC", "DE ", "MC" });
string s = ParseData(s, prefixes,HasPrefix, ParsePrefix);

private const string[] suffixes = { " II", " III", " IV");
return ParseData(s, suffixes ,HasSuffix, ParseSuffix);
}

private string ParseData(string input, string[] data, Func<string, string, bool> hasData, Func<string, string, string> getData)
{

foreach(string item in data)
{
if (hasData(input, prefix)
{
return getData(input, prefixes);
}
}

return input;
}

private bool HasPrefix(string input, string prefix)
{
int length = prefix.length + 1;
return (s.ToUpper().StartsWith(prefix)) && input.Length > length;
}

private string ParsePrefix(string input, string prefix)
{
int length = prefix.length;
return input.Substring(0, 1).ToUpper() + input.Substring(1, length - 1).ToLower() + s.Substring(length, 1).ToUpper() + s.Substring(length + 1).ToLower();
}

private string ParseSuffix(string input, string suffix)
{
int length = suffix.length;
return s.Substring(0, input.ToUpper().IndexOf(suffix)) + " " + s.Substring(s.ToUpper().IndexOf(suffix), length).ToUpper();
}

private bool HasSuffix(string input, string suffix)
{
return input.ToUpper().Contains(suffix);
}

4
ответ дан 8 октября 2011 в 08:10 Источник Поделиться