You gave as an example "josé da silva", so I am assuming that the string will not necessarily have capitalized and lowercase letters correctly (as a name would normally have, for example: "José da Silva"). That is, I understand that we can have cases like "josé da Silva", "José da Silva", etc.
The problem of making one loop character by character is that you will have to manually assemble the substrings containing each part of the name. Instead, you can use split
to separate the string by spaces.
Then, for each part, just see if it is one of the connectors. If it is not, add the initial. Something like this:
String nome = "josé da silva";
List<String> conectores = Arrays.asList("do", "da", "de"); // coloque aqui todos os conectores que precisar
StringBuilder iniciais = new StringBuilder();
for (String parte: nome.split(" ")) {
if (! conectores.contains(parte.toLowerCase())) { // se não é um conector
iniciais.append(Character.toUpperCase(parte.charAt(0)));
}
}
System.out.println("Iniciais: " + iniciais.toString()); // JS
First the split
separates the string by spaces, so I can check each part of the name separately.
I created a list of connectors (all in lower case), and for each part of the name I check if it is a connector. If not, I add the first letter (uppercase) in the StringBuilder
. You could even concatenate the strings into for
, but in a loop, use StringBuilder
is more efficient.
It is unclear whether there is always exactly one space separating each name. If you have more than one space between them, just switch to nome.split(" +")
- the parameter of split
is a regular expression (regex) and in the case of quantifier +
means "one or more occurrences" (ie, " +"
means "one or more spaces"). You could also use nome.split("\\s+")
, only that the shortcut \s
also considers characters other than space, such as TAB and line breaks (see more details here).
Another alternative (unnecessarily complicated, stays here only as "curiosity") is to do the split
considering the connectors themselves:
String nome = "josé da silva DOS SANTos";
StringBuilder iniciais = new StringBuilder();
for (String parte : nome.split("(?i)\\s+(d[aeo]s?)\\s+")) {
iniciais.append(Character.toUpperCase(parte.charAt(0)));
}
System.out.println("Iniciais: " + iniciais.toString()); // JSS
To inline flag (?i)
indicates that regex will be case insensitive (does not differentiate uppercase from lowercase). Then we have one or more spaces, followed by d[aeo]s?
. To character class [aeo]
take the letter "a," or "e," or "o," and the s?
indicates that the letter "s" is optional (I did so to accept "de", "do", "da", "dos", "das" and "des"). Therefore, this regex takes all these connectors, containing spaces before and after.
Thus, the return of the split
will already delete the connectors (and also the spaces before and after them), not needing to check them inside the loop.
But as I said, I find it unnecessarily complicated, being simpler to keep a list of all connectors, as the first suggestion above (as this list grows, the regex will become more and more complex).
I would return all uppercase letters, but before I would do a function that separate using the space character and then would check if the initial letter is uppercase.
– Maury Developer