Check if a String contains two words

Asked

Viewed 2,089 times

4

I have a problem with this exercise here:

Write a class that validates data (Validacao), with a method to validate a given name (ehNomeValido(nome)). The method must return true pass the following rules:

  • If the parameter is not null.

  • If the parameter is not a String empty

  • If the parameter has two particles (two words separated by a space)

The problem is that the program only returns me the false in the case of the name I put as parameter the program should return true. Where am I wrong? I’ve rewritten the code several times in other ways and nothing.

 public class NOVOTESTE2{

     public static boolean validacao(String nome){
         if((nome != null) && (nome.isEmpty() == false) && (nome.indexOf(" ") == 1)){
             return true;
         }else{
             return false;
         }     
     }

  public static void main(String[] args){

        System.out.println(validacao("Rodrigo Moreira"));
  }  
}
  • 5

    Please make an intuitive title for the question, write help please is totally redundant, everyone who are asking on the site are already looking for help, so it’s obvious, write a useful title setting the problem helps to increase people’s interest.

  • @Gandalf, the code should also cover names with more than 2 words?

  • Did any of the answers solve your question? Do you think you can accept one of them? Check out the [tour] how to do this, if you haven’t already. You would help the community by identifying what was the best solution for you. You can accept only one of them. But you can vote on any question or answer you find useful on the entire site.

6 answers

13

This? It seems that the problem is that you are trying to check wrong thing if there is more than one word.

public static boolean validacao(String nome) {
    return nome != null && !nome.isEmpty() && new StringTokenizer(nome).countTokens() > 1;
}

After seeing the solutions and reading documentation, do some tests I think this form is the simplest and most reliable because it was made to meet precisely this demand. I’m still not sure if you have corner cases.

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

StringTokenizer

7

A suggestion with regex, which will probably accept accentuation and will also work with CASE-INSENTIVE, would be using so:

public static boolean validacao(String nome){
    return nome != null && nome.matches("^\\p{L}+ [\\p{L} ]+$"));
}

Nor is it necessary to isEmpty in this case with REGEX, if you need exactly two words just change to:

nome.matches("^\\p{L}+ \\p{L}+$"))

If you don’t need an accent, then you can use the a-z, the \w may work too, but his problem is that he accepts underscore _, and this does not seem correct in a name validation, so the regex can look like this (using the (?i:...) for case-insensitive can help decrease complex regular expressions):

public static boolean validacao(String nome){
    return nome != null && nome.matches("^(?i:[a-z]+ [a-z ]+)$"));
}

If you need exactly 2 words change to:

nome.matches("^(?i:[a-z]+ [a-z]+)$"))

In both examples I did accept one or more surnames, ie two or more words in the string.


Explaining the regular expressions

To the ^\\p{L}+ [\\p{L} ]+$:

  • ^ checks if the expression starts with
  • \\p{L}+ checks words until you find a space (note that after the + has a space)
  • [\\p{L} ]+$ checks words and spaces, ie can contain more than one word with space until you find the end of the string

To the ^(?i:[a-z]+ [a-z ]+)$:

  • ^ checks if the expression starts with
  • (?i: initiating a group case-insensitive
  • [a-z]+ checks words with a-z letters until you find a space (note that after the + has a space)
  • [a-z ]+) checks words with letters of a-z and spaces, ie may contain more than one word with space until you find the end of the group (group for case-insensitive)
  • $ checks whether the string ends exactly according to the expression

5

indexOf(" ") returns the position the space is in String, therefore it will not necessarily be 1. It would be right to test if the value is different from -1, since this is the value returned if there are no spaces.

The problem is that indexOf only checks if there is any white space.
If the entrance is " " (multiple spaces), for example, or if the space is at the beginning or end, indexOf it won’t do any good.

One way to check if it has two words is to use what the @Maniero suggests in his reply. Another way is to use regular expression, to make sure that before and after space you actually have a word - assuming that "word" is a string of uppercase or lowercase letters:

public static boolean validacao(String nome){
    return (nome != null) && (! nome.isEmpty()) && nome.matches("^[a-zA-Z]+ [a-zA-Z]+$");
}
  • ^ indicates the beginning of String
  • [a-zA-Z]+ indicates one or more occurrences of upper or lower case letters
  • $ indicates the beginning of String

See more details about regular expression in this tutorial. Also note that as the return of the method is a boolean, you can directly return the result of the checks (as well remembered in the comments).

One detail is that the regex will only work for exactly two words. But you can change the $ for .*, which then works for several words (and should have at least two).

And will not accept accented characters as pointed out in the comments.

  • 2

    I thought the idea of regex was cool, except that names can contain more than one surname, your regex only accepts one surname, something else, why so many parentheses?

  • 1

    The if is already unnecessary. Just return the comparison itself.

  • Another detail, accents will not work with this type of regex a-za-Z is only for letters without accent.

  • @Guilhermenascimento I now realized my mistake with respect to two words. My regex only validated exactly two words, but the string may have more. I edited the answer, thank you! And for the accents, I swapped a-za-z for w and it worked, but I don’t know if this is something that depends on the JVM Locale, so for now I left anyway.

  • I believe that \w do not work with accents in a "regular" way, which complicates everything, to avoid more debate and I can show you the way more quickly, a suggestion that perhaps meets everything: https://answall.com/a/15741/3635

0

The problem is in the index, It will return the position of space, that in the casó is 7.

I believe the approach below should be more assertive to find the word with only one space

    public static boolean validacao(String nome){
        if(nome != null && !nome.isEmpty() && nome.split(" ").length == 2){
            return true;
        }else{
            return false;
        }
    }
  • If it has 3 words it will give false negative.

  • Because Return false and Return true, this is pure redundancy, you can put everything inside the direct Return, another detail, ==2 will only allow a name and a surname, if the person has a larger surname there will be a problem.

  • 1

    Friends, the description is as follows: "If the parameter has two particles (two words separated by a space)". No, more than two particles... Yes is redundant, but it is friendlier to read for those who are starting...

  • Initially I had also thought that it would be exactly two particles, but when you think about it, the statement can be interpreted as "at least two"...

  • Marlon’s code covers the cases the author raised. I don’t understand the reason for two negatives. If it has 3 words the name will be refused as expected and, if this were not the case, the correction would be simple.

-2

indexof will give -1 or the space the string shows the desired char. In his comparison he only verifies that the space comes after the first letter, example: j john would work, you just need in your comparison to check if the index(" ") is different from -1, so:

public static boolean validacao(String nome){
         if ((nome != null) && (nome.isEmpty() == false) && (nome.indexOf(" ") != -1)){
             return true;
         } else {
             return false;
         }     
     }
  • 1

    Why so many relatives? Why == false, a simple !nome.isEmpty() would no longer solve?

  • I only copied the code already written from him, but I agree that I have several excerpts of unnecessary codes

  • 4

    If space is at the beginning or at the end it will have only one word and give a false positive, so this is wrong.

-2

Gandalf, as you are learning, I took the liberty of tweaking the original code and running the necessary tests (very important).

Look at the code:

public static class NovoTeste2 {

    public static boolean validacao(String nome){
        return (nome != null) && (!nome.isEmpty()) && (nome.split(" ").length >= 2);
    }
}

In the above code, I simplified checking the name to be empty (you don’t need the == false) and, to validate whether the name has only two words, I split the String using the blank space, hoping that the array generated by the split has at least 2 elements. I also changed the class name to a Java default name (using Camelcase).

If you want to restrict to only two words, just change of length >= 2 for length == 2.

And finally, the code above with the tests for each case:

public class TemAoMenosDuasPalavrasTest {

    @Test
    public void nomeCorreto() {
        assertTrue(NovoTeste2.validacao("Augusto Nonato"));
    }

    @Test
    public void nomeComTresPalavras() {
        assertTrue(NovoTeste2.validacao("Augusto Nonato Junior"));
    }

    @Test
    public void nomeSemDuasPalavras() {
        assertFalse(NovoTeste2.validacao("Augusto"));
    }

    @Test
    public void nomeNulo() {
        assertFalse(NovoTeste2.validacao(null));
    }

    @Test
    public void nomeVazio() {
        assertFalse(NovoTeste2.validacao(""));
    }

    @Test
    public void nomeVazioComEspacos() {
        assertFalse(NovoTeste2.validacao("   "));
    }

    public static class NovoTeste2 {

        public static boolean validacao(String nome){
            return (nome != null) && (!nome.isEmpty()) && (nome.split(" ").length >= 2);
        }
    }
}

This makes it much easier to know if your code is working even after changes and for all expected cases.

Remembering that I did not treat all possible cases: valid name with more than one space between words, extra spaces at the beginning or end of the name, etc.

  • Two negatives (one followed by the other), without explaining the reason and I added tests to cover the cases raised by the author of the question.

  • "Augusto Nonato Junior" would false, but contains two words yes. The author did not restrict the validation to "contains exactly two words", then your code generates the same problem as the other answer.

  • @Articuno the question title is wrong then? " Check if a String contains two words"

  • No mistake in the title no, as I said, the author nay restricted at any time that should have exactly two words.

  • So it should be "at least two words".

  • @Articuno I will correct the title of the question (which is confused) and the code above.

  • This is up to the author define better, but as it did not define, it was what was understood, since there is no mention of restriction.

Show 2 more comments

Browser other questions tagged

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