C# - name separation & last name in upper to Camel I had an xls file with lots of full names in the following form at work:
+----------------------------+--------------+-----+-----+
|        [Full name]         | [More data]  |[...]|[...]|
+----------------------------|--------------------------+
|   Cristiano RONALDO        |     ...      | ... | ... |
+----------------------------+--------------+-----+-----+
|   Carol SEVILLA            |     ...      | ... | ... |
+----------------------------|--------------+-----+-----+
|   Ronald Chris MAC DONALDS |     ...      | ... | ... |
+----------------------------|--------------+-----+-----+

some of the data will still be input this way but I want to add a column for last name and let it clear that I don't need the last name in upper case anymore, so I separated name from last name, and then changed the last name to camel case, notice that last names can have many words like &quot;Mc Donalds Rodriguez&quot; (it happens) so I solved it as follows
public static string GetLastNameFromFullName(string fullName)
{
    var lastName = &quot;&quot;;
    foreach (var ch in fullName)
    {
        lastName += ch;
        if (char.IsLower(ch))
        {
            lastName = &quot;&quot;;
        }
    }
    return lastName.TrimStart();
}

public static string GetCameledLastName(string lastNames)
{
    string[] lastNamesArr = lastNames.Split(' ');
    var lastNamesCameled = &quot;&quot;;

    foreach (string lastNameUpper in lastNamesArr)
    {
        lastNamesCameled += lastNameUpper[0];
        for (int i = 1; i &lt; lastNameUpper.Length; i++)
        {
            lastNamesCameled += char.ToLower(lastNameUpper[i]);
        }
    }
    return lastNamesCameled;
}

public static string GetNameWithoutLastName(string fullName)
{
    var possibleLastName = false;
    char possibleLastNameChar = ' '; //just initialized
    var name = &quot;&quot;;
    foreach (var ch in fullName)
    {
        if (char.IsUpper(ch))
        {
            possibleLastNameChar = ch;
            if (possibleLastName)
            {
                break;
            }
            possibleLastName = true;
        }
        else
        {
            if (possibleLastName)
            {
                name += possibleLastNameChar;
            }
            name += ch;
            possibleLastName = false;
        }
    }
    return name;
}
private void Form1_Load(object sender, EventArgs e)
{
    var path = @&quot;../../file.txt&quot;; //dumped from xls file
    string contents = File.ReadAllText(path);

    using (StreamReader reader = new StreamReader(path, Encoding.GetEncoding(&quot;iso-8859-1&quot;))) //some names had ñ or accented characters
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            var fullName = &quot;&quot;;
            foreach (char ch in line)
            {
                if (ch == '\t')
                {
                    //The columns in the xls file were divided by tab characters
                }
                else
                {
                    fullName += ch;
                }
            }
            var lastName = GetLastNameFromFullName(fullName);
            Console.WriteLine(&quot;Name: &quot; + GetNameWithoutLastName(fullName));
            Console.WriteLine(&quot;Last name: &quot; + GetCameledLastName(lastName));
        }
    }
}

I think my code could be a lot better.
UPDATE: please note that while it is true that cases like &quot;Cinthia del Río&quot; is an actual name that is not considered in this way, it will be converted to &quot;Cinthia Del Rio&quot; because in the xls file it would be in a single column as &quot;Cinthia DEL RIO&quot;, and of course it is impossible for the algorithm to know that &quot;DEL&quot; should actually be &quot;del&quot; even though it is perfectly OK for a last name's word to start with a lower case.
Well, I don't know if your code could be better or faster but the code could be a lot shorter by using some Linq-&quot;magic&quot;.
Your code could use some level of input-parameter-validation because the methods in question are public which means anybody who uses these methods can pass whatever he/she wants, even null which would blow each method and would expose implementation details.
I don't know if the requirement is meant to be that passing Ronald Chris MAC DONALDS returns as lastname MacDonalds but for me this doesn't sound correct.
Instead of splitting the fullname twice and then splitting the lastname again, you should consider to just pass a string[] to the methods.
You could consider to have one public method where you pass the fullname and get a Tuple&lt;string, string&gt; so you would need only one parameter validation because you can make the other methods private.
Because a lastname contains only UpperCase letters we can take the passed string[] and take each string in this array which contains only upper-case letters, we will leave the first char because it allready is uppercase and take the remaining chars as lower-case chars. Last we join them using a space char like so
private static string GetLastName(string[] nameParts)
{
    return string.Join(&quot; &quot;, nameParts.Where(s =&gt; s.All(c =&gt; char.IsUpper(c)))
                                     .Select(s =&gt; s[0] + s.Substring(1).ToLowerInvariant()));
}  

For the firstname we know that not all chars are upper-case chars. So we take each string inside the passed array and check if any char is a lower-case char, and then join the found strings by using a space char like so
private static string GetFirstName(string[] nameParts)
{
    return string.Join(&quot; &quot;, nameParts.Where(s =&gt; s.Any(c =&gt; char.IsLower(c))));
}  

Last but not least we need to call these 2 methods after some proper validation like so
public static Tuple&lt;string, string&gt; GetNormalizedNames(string fullName)
{
    if (fullName == null) { throw new ArgumentNullException(nameof(fullName)); }
    if (string.IsNullOrWhiteSpace(fullName)) { return Tuple.Create(&quot;&quot;, &quot;&quot;); }

    var nameParts = fullName.Split(' ');

    return Tuple.Create(GetFirstName(nameParts), GetLastName(nameParts));
}  

which we then call like so
var firstNameLastNameTuple = GetNormalizedNames(fullName);
Console.WriteLine(&quot;Name: &quot; + firstNameLastNameTuple.Item1);
Console.WriteLine(&quot;Last name: &quot; + firstNameLastNameTuple.Item2);  

The whole code is now easier to read and therefor easier to maintain. Sure linq is only syntactic sugar and won't be faster than iterating over the chars by &quot;hand&quot; but the benefit is less and easier to read code.