Заглавные слова в строке с использованием c#
Мне нужно взять строку и заглавными словами в ней. Некоторые слова ("in", " at " и т. д.), не капитализируются и изменяются на нижний регистр, если встречаются. Первое слово всегда должно быть заглавной буквой. Фамилии, такие как "McFly", не находятся в текущей области, поэтому к ним будет применяться то же правило - только первая буква с заглавной буквы.
например: "мышей и мужчин CNN "следует изменить на"мышей и мужчин CNN". (поэтому ToTitleString не будет работать вот!--4-->)
Мне интересно, что было бы лучшим способом сделать это. Я подумал о том, чтобы разбить строку на пробелы и пройтись по каждому слову, при необходимости изменяя его, связывая с предыдущим словом и так далее. Это кажется довольно наивным, и мне было интересно, есть ли лучший способ сделать это, используя .Net 3.5.
10 ответов
в зависимости от того, как часто вы планируете делать капитализации, я бы пошел с наивным подходом. Вы могли бы сделать это с регулярным выражением, но тот факт, что вы не хотите, чтобы определенные слова были заглавными, делает это немного сложнее.
Edit:
вы можете сделать это с двумя проходами, используя regexes
var result = Regex.Replace("of mice and men isn't By CNN", @"\b(\w)", m => m.Value.ToUpper());
result = Regex.Replace(result, @"(\s(of|in|by|and)|\'[st])\b", m => m.Value.ToLower(), RegexOptions.IgnoreCase);
выводит Of Mice and Men Isn't by CNN
.
первое выражение капитализирует каждую букву на границе слова, а второе-любое слова, соответствующие списку, которые окружены пробелами.
недостатками этого подхода является то, что вы используете регулярные выражения (теперь у вас есть две проблемы), и вам нужно будет сохранить этот список исключенных слов в актуальном состоянии. Мой regex-fu недостаточно хорош, чтобы сделать это в одном выражении, но это может быть возможно.
использовать
Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase("of mice and men By CNN");
для преобразования в правильный случай, а затем вы можете перебирать ключевые слова, как вы упомянули.
здесь ответ Как заработать именами
CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
TextInfo textInfo = cultureInfo.TextInfo;
Console.WriteLine(textInfo.ToTitleCase(title));
Console.WriteLine(textInfo.ToLower(title));
Console.WriteLine(textInfo.ToUpper(title));
почему бы не использовать ToTitleCase()
сначала, а затем сохранить список применимых слов и Replace
вернуться к строчной версии этих применимых слов (при условии, что список небольшой).
Список применимых слов может быть сохранен в словаре и зациклен довольно эффективно, заменяя .ToLower()
эквивалентны.
попробуйте что-то вроде этого:
public static string TitleCase(string input, params string[] dontCapitalize) {
var split = input.Split(' ');
for(int i = 0; i < split.Length; i++)
split[i] = i == 0
? CapitalizeWord(split[i])
: dontCapitalize.Contains(split[i])
? split[i]
: CapitalizeWord(split[i]);
return string.Join(" ", split);
}
public static string CapitalizeWord(string word)
{
return char.ToUpper(word[0]) + word.Substring(1);
}
вы можете позже обновить CapitalizeWord
метод, если вам нужно обрабатывать сложные фамилии.
Добавьте эти методы в класс и используйте его следующим образом:
SomeClass.TitleCase("a test is a sentence", "is", "a"); // returns "A Test is a Sentence"
вы можете иметь словарь, имеющий слова, которые вы хотели бы игнорировать, разделить предложение на фразы (.split ( '' )) и для каждой фразы проверьте, существует ли фраза в словаре, если нет, заглавной буквы первого символа, а затем добавьте строку в буфер строк. Если фраза, которую вы сейчас обрабатываете, находится в словаре, просто добавьте ее в буфер строк.
небольшое улучшение ответа Джонни:
var result = Regex.Replace(s.Trim(), @"\b(\w)", m => m.Value.ToUpper());
result = Regex.Replace(result, @"\s(of|in|by|and)\s", m => m.Value.ToLower(), RegexOptions.IgnoreCase);
result = result.Replace("'S", "'s");
неумный подход, который обрабатывает простой случай:
var s = "of mice and men By CNN";
var sa = s.Split(' ');
for (var i = 0; i < sa.Length; i++)
sa[i] = sa[i].Substring(0, 1).ToUpper() + sa[i].Substring(1);
var sout = string.Join(" ", sa);
Console.WriteLine(sout);
самым простым очевидным решением (для английских предложений) было бы:
-
"sentence".Split(" ")
предложение о пробелах - цикл через каждый элемент
- заглавная первая буква каждого элемента -
item[i][0].ToUpper()
, - вернитесь в строку, соединенную с пробелом.
- повторите этот процесс с "."и", " используя эту новую строку.