Pick first and last name and abbreviate middle names only with the initial

Asked

Viewed 20,560 times

6

I would like to address the following string:

string nome = "Rafael Rodrigues Arruda de Oliveira"

With the following criteria::

  • Keep first and last name;
  • Abbreviate the other names (middle names) with the initial of the same;
  • Insert a dot (".") after abbreviation;
  • Prevent abbreviation in the case of: "de","da","do","das","dos";
  • Only the initial of the name must be uppercase;

Output expected: Rafael R. A. Oliveira

  • 2

    To avoid long discussions in the comments your conversation was moved to the chat and can proceed there by the link provided.

  • 1

    Perfect question, I was looking for something like that, thank you!

3 answers

14


This is much better:

using static System.Console;
using System;

public class Program {
    public static void Main() {
        WriteLine(Abreviatte("Rafael Rodrigues Arruda de Oliveira"));
        WriteLine(Abreviatte("Rafael Rodrigues Arruda De Oliveira"));
    }
    public static string Abreviatte(string nome) {
        var meio = " ";
        var nomes = nome.Split(' ');
        for (var i = 1; i < nomes.Length - 1; i++) {
            if (!nomes[i].Equals("de", StringComparison.OrdinalIgnoreCase) &&
                !nomes[i].Equals("da", StringComparison.OrdinalIgnoreCase) &&
                !nomes[i].Equals("do", StringComparison.OrdinalIgnoreCase) &&
                !nomes[i].Equals("das", StringComparison.OrdinalIgnoreCase) &&
                !nomes[i].Equals("dos", StringComparison.OrdinalIgnoreCase))
                    meio += nomes[i][0] + ". ";
        }
        return nomes[0] + meio + nomes[nomes.Length - 1];
    }
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

I’ve eliminated variables and unnecessary allocations. Only do operations you need in your code, if you want to compare disregarding the letter box then compare like this, do not create a string for nothing and then compare it with something else.

Note that I would normally use StringBuilder, But I’m considering that almost never more than four middle names, so concatenation is acceptable. And I’m also considering that you don’t need the maximum optimization, otherwise the correct would be to use Span.

In the AP code and the other answer with LINQ, the comparison in each existing middle name are 8 allocations against one of my code, but it is possible to eliminate even this allocation with the techniques cited.

Allocating more doesn’t make the answers wrong, I’m just giving you a more efficient option. But allocation is something that greatly impairs execution, and what may not make a difference an hour is used in a big loop and causes a huge problem. No wonder that much of the C# and . NET improvements have turned to decrease allocations.

In fact for maximum performance should not use Split() also and operate character by character, but in general this is not a requirement so also did not do it.

  • 3

    If the people who saw the error in my answer can inform me.

9

One more example using and abusing Linq...

string nome = "Rafael Rodrigues Arruda de Oliveira";

var preposicoes = new string[] { "de", "da", "do", "das", "dos" };

var nomes = nome.ToLower().Split(' ').Where(x => !string.IsNullOrEmpty(x) && !preposicoes.Contains(x));

string result = $"{nomes.First()} {string.Concat(nomes.Skip(1).Take(nomes.Count() - 2).Select(x => x.First() + ". "))}{nomes.Last()}";

result = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(result);
  • 1

    It’s cool, there’s only one detail, the code doesn’t do what the AP wants. I understand you, after all the question does not give the criteria to do, and this is one of the reasons it is closed, but the answer of the AP gives the criteria and needs to disregard capitalization and minuscule. If improve this I think it looks good (still inefficient equal the AP response, but at least does what the AP wants).

  • @Maniero One option would be to pass the string name for ToLower() and then the string result for Textinfo.Totitlecase(), thus avoiding outputs with RAfael or rafael. Leaving the inefficiency aside, would advise the use of the method ToTitleCase()? That according to the documentation may change in the future.

  • I believe that does not solve this case no. The ToLower() resolves, despite inefficient.

  • 2

    @Maniero it seems you didn’t understand me, the use of ToTitleCase() would only be at the end of the code to pass all initials to uppercase,.

  • 1

    But that’s not the point, what you’re saying would be a bonus, but it doesn’t solve the problem of comparing stop words. The one you are talking about now is not part of the original need (at least nothing in the question or answer that served as a reference indicates it), only would be worth as a bonus, although I would do different from this because of the efficiency.

  • @Maniero edited the code as I wrote in my first comment, which solves the problem of stop words (that you did not understand, or I expressed myself badly), what you wanted was an opinion on the use of ToTitleCase()...

  • Yes, the problem has been solved.

Show 2 more comments

1

string nome = "Rafael Rodrigues Arruda de Oliveira";
string primeiro = "";
string meio = " "; // Sim, tem um espaço aqui!
string ultimo = "";

string[] nomes = nome.Split(' '); // Separa cada nome pelo espaço.

primeiro = nomes[0]; // Reserva o primeiro nome.

for (int i = 1; i < nomes.Length - 1; i++) 
{
    if (!nomes[i].ToLower().Equals("de") && !nomes[i].ToLower().Equals("da") && !nomes[i].ToLower().Equals("do") && !nomes[i].ToLower().Equals("das") && !nomes[i].ToLower().Equals("dos"))
    {
         meio += nomes[i].Substring(0, 1); // Reserva a inicial do próximo nome.
         meio += ". "; // Põe um ponto e um espaço após a inicial.
    }
}

ultimo = nomes[nomes.Length-1]; // Reserva o ultimo nome.

nome = primeiro + meio + ultimo; // Junta todos os nomes.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.