diff --git a/strings-csharp/StringToTitleCase/StringToTitleCase/Program.cs b/strings-csharp/StringToTitleCase/StringToTitleCase/Program.cs index 2fdc9f9885..f789764c4e 100644 --- a/strings-csharp/StringToTitleCase/StringToTitleCase/Program.cs +++ b/strings-csharp/StringToTitleCase/StringToTitleCase/Program.cs @@ -1,21 +1,25 @@ -using System; -using System.Globalization; +using System.Globalization; +using StringToTitleCase; -namespace StringToTitleCase -{ - class Program - { - static void Main(string[] args) - { - var textinfo = new CultureInfo("en-US", false).TextInfo; +var textinfo = new CultureInfo("en-US", false).TextInfo; - var textInfo = CultureInfo.CurrentCulture.TextInfo; +Console.WriteLine(textinfo.ToTitleCase("a tale oF tWo citIes")); +Console.WriteLine(textinfo.ToTitleCase("harry potter and the Deathly hallows")); - Console.WriteLine(textinfo.ToTitleCase("a tale oF tWo citIes")); +Console.WriteLine(textinfo.ToTitleCase("OLIVER TWIST")); +Console.WriteLine(textinfo.ToTitleCase(textinfo.ToLower("OLIVER TWIST"))); +Console.WriteLine(textinfo.ToTitleCase(textinfo.ToLower("THE NASA MISSION"))); - Console.WriteLine(textinfo.ToTitleCase("harry potter and the Deathly hallows")); +Console.WriteLine("a tale oF tWo citIes".ToTitleCaseWithMinorWords(textinfo)); +Console.WriteLine("harry potter and the Deathly hallows".ToTitleCaseWithMinorWords(textinfo)); - Console.WriteLine(textinfo.ToTitleCase("OLIVER TWIST".ToLower())); - } - } -} +Console.OutputEncoding = System.Text.Encoding.UTF8; +var turkish = new CultureInfo("tr-TR", false).TextInfo; +Console.WriteLine(turkish.ToTitleCase("a tale oF tWo citIes")); +Console.WriteLine(turkish.ToTitleCase("istanbul")); +Console.WriteLine(CultureInfo.InvariantCulture.TextInfo.ToTitleCase("a tale oF tWo citIes")); + +Console.WriteLine(textinfo.ToTitleCase("the 2nd edition")); +Console.WriteLine(textinfo.ToTitleCase("my iPhone")); +Console.WriteLine(textinfo.ToTitleCase("mcdonald's menu")); +Console.WriteLine(textinfo.ToTitleCase("x-ray vision")); diff --git a/strings-csharp/StringToTitleCase/StringToTitleCase/StringToTitleCase.csproj b/strings-csharp/StringToTitleCase/StringToTitleCase/StringToTitleCase.csproj index 41f1d5ad4b..dfb40caafc 100644 --- a/strings-csharp/StringToTitleCase/StringToTitleCase/StringToTitleCase.csproj +++ b/strings-csharp/StringToTitleCase/StringToTitleCase/StringToTitleCase.csproj @@ -2,7 +2,9 @@ Exe - net6.0 + net10.0 + enable + enable diff --git a/strings-csharp/StringToTitleCase/StringToTitleCase/TitleCaseExtensions.cs b/strings-csharp/StringToTitleCase/StringToTitleCase/TitleCaseExtensions.cs new file mode 100644 index 0000000000..debd77993b --- /dev/null +++ b/strings-csharp/StringToTitleCase/StringToTitleCase/TitleCaseExtensions.cs @@ -0,0 +1,26 @@ +using System.Globalization; + +namespace StringToTitleCase; + +public static class TitleCaseExtensions +{ + private static readonly HashSet MinorWords = new(StringComparer.OrdinalIgnoreCase) + { + "a", "an", "and", "as", "at", "but", "by", "for", "in", "nor", "of", "on", "or", "the", "to" + }; + + public static string ToTitleCaseWithMinorWords(this string input, TextInfo textInfo) + { + var words = textInfo.ToTitleCase(textInfo.ToLower(input)).Split(' '); + + for (var i = 1; i < words.Length - 1; i++) + { + if (MinorWords.Contains(words[i])) + { + words[i] = textInfo.ToLower(words[i]); + } + } + + return string.Join(' ', words); + } +} diff --git a/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.cs b/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.cs index 4c20206d1b..3f6c8ce173 100644 --- a/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.cs +++ b/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.cs @@ -1,31 +1,84 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Globalization; +using StringToTitleCase; -namespace StringToTitleCaseUnitTest +namespace StringToTitleCaseUnitTest; + +[TestClass] +public class StringToTitleCaseUnitTest { - [TestClass] - public class StringToTitleCaseUnitTest + private readonly TextInfo textInfo = new CultureInfo("en-US", false).TextInfo; + + [TestMethod] + public void GivenToTitleCase_WhenStringIsPassed_ConversionToTitleCaseSuccessful() { - private readonly TextInfo textInfo = CultureInfo.CurrentCulture.TextInfo; + Assert.AreEqual("A Tale Of Two Cities", textInfo.ToTitleCase("a tale oF tWo citIes")); - [TestMethod] - public void GivenToTitleCase_WhenStringIsPassed_CoversionToTitleCaseSuccessful() - { - Assert.AreEqual("A Tale Of Two Cities", textInfo.ToTitleCase("a tale oF tWo citIes")); + Assert.AreEqual("Harry Potter And The Deathly Hallows", textInfo.ToTitleCase("harry potter and the Deathly hallows")); + } - Assert.AreEqual("Harry Potter And The Deathly Hallows", textInfo.ToTitleCase("harry potter and the Deathly hallows")); - } + [TestMethod] + public void GivenToTitleCase_WhenWordWithAllUpperCaseIsPassed_ConversionToTitleCaseNotSuccessful() + { + Assert.AreEqual("OLIVER TWIST", textInfo.ToTitleCase("OLIVER TWIST")); + } - [TestMethod] - public void GivenToTitleCase_WhenWordWithAllUpperCaseIsPassed_ConversionToTitleCaseNotSuccessful() + [TestMethod] + public void GivenToTitleCase_WhenWordWithAllUpperCaseIsPassed_ConversionToTitleCaseSuccessful() + { + Assert.AreEqual("Oliver Twist", textInfo.ToTitleCase(textInfo.ToLower("OLIVER TWIST"))); + } + + [TestMethod] + public void GivenToTitleCase_WhenAcronymIsLowercasedFirst_AcronymIsLost() + { + Assert.AreEqual("The NASA Mission", textInfo.ToTitleCase("the NASA mission")); + + Assert.AreEqual("The Nasa Mission", textInfo.ToTitleCase(textInfo.ToLower("THE NASA MISSION"))); + } + + [TestMethod] + public void GivenCurrentCultureIsTurkish_WhenStringToLowerIsUsed_DotlessIAppears() + { + var original = CultureInfo.CurrentCulture; + try { - Assert.AreNotEqual("Oliver Twist", textInfo.ToTitleCase("OLIVER TWIST")); - } + CultureInfo.CurrentCulture = new CultureInfo("tr-TR"); - [TestMethod] - public void GivenToTitleCase_WhenWordWithAllUpperCaseIsPassed_ConversionToTitleCaseSuccessful() + Assert.AreEqual("Olıver Twıst", textInfo.ToTitleCase("OLIVER TWIST".ToLower())); + Assert.AreEqual("Oliver Twist", textInfo.ToTitleCase(textInfo.ToLower("OLIVER TWIST"))); + } + finally { - Assert.AreEqual("Oliver Twist", textInfo.ToTitleCase("OLIVER TWIST".ToLower())); + CultureInfo.CurrentCulture = original; } } + + [TestMethod] + public void GivenToTitleCaseWithMinorWords_WhenStringIsPassed_MinorWordsStayLowercase() + { + Assert.AreEqual("A Tale of Two Cities", "a tale oF tWo citIes".ToTitleCaseWithMinorWords(textInfo)); + + Assert.AreEqual("Harry Potter and the Deathly Hallows", "harry potter and the Deathly hallows".ToTitleCaseWithMinorWords(textInfo)); + + Assert.AreEqual("The Lord of the Rings", "the lord of the rings".ToTitleCaseWithMinorWords(textInfo)); + } + + [TestMethod] + public void GivenToTitleCase_WhenCultureIsTurkish_ResultUsesTurkishCasing() + { + var turkish = new CultureInfo("tr-TR", false).TextInfo; + + Assert.AreEqual("A Tale Of Two Citıes", turkish.ToTitleCase("a tale oF tWo citIes")); + Assert.AreEqual("İstanbul", turkish.ToTitleCase("istanbul")); + Assert.AreEqual("A Tale Of Two Cities", CultureInfo.InvariantCulture.TextInfo.ToTitleCase("a tale oF tWo citIes")); + } + + [TestMethod] + public void GivenToTitleCase_WhenWordHasDigitsOrInnerCapitals_ResultIsNotWhatAHumanWrites() + { + Assert.AreEqual("The 2Nd Edition", textInfo.ToTitleCase("the 2nd edition")); + Assert.AreEqual("My Iphone", textInfo.ToTitleCase("my iPhone")); + Assert.AreEqual("Mcdonald's Menu", textInfo.ToTitleCase("mcdonald's menu")); + Assert.AreEqual("X-Ray Vision", textInfo.ToTitleCase("x-ray vision")); + } } diff --git a/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.csproj b/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.csproj index 0ef0e0cb63..4df3b9a29c 100644 --- a/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.csproj +++ b/strings-csharp/StringToTitleCase/StringToTitleCaseUnitTest/StringToTitleCaseUnitTest.csproj @@ -1,16 +1,21 @@ - net6.0 - + net10.0 + enable + enable false - - - - + + + + + + + +