How can I check duplicated words within an Array and count them?

108 Views Asked by At

I just started programming with JAVA 2 months ago and currently I'm facing an exercise which I don't find the solution for. Until now I control (kind of) the following structures: if (else), do while, while, for, basic array and matrix management, so the exercise is intended to be solved with some of them.

And the exercise says: "Build a simple program that asks for three words and tells you the number of different words or how many are the same. The process will be repeated until one of the words is "exit"." So far this is what I got:

    String [] names = new String [3];

        int index=0;
        boolean found=false;
        int position=0;
        for (int i=0; i<names.length; i++) {
            if (i==0) {
            System.out.println("User, give me name");
            names[i]=lector.nextLine();
            if (names[i].equals("exit")) {
                break;
            }
            } else {
                System.out.println("Give me another name");
                names[i]=lector.nextLine();
                i=position;
                found=false;
                if (names[i].equals("exit")) {
                    break;
                }
                do {
                    if (names[position].equals(names[i-1])) {
                        found=true;

                    }
                    index++;
                } while (position>=0 && !found);
                
            }
        }
        System.out.println("Repeated words: "+index);

So I have to use the scanner and let the user write three words under the previous rules.

I'm talking about arrays as it's the first and only way I find to solve the problem, but there may be others.
I'm getting an out of bounds error and I honestly have no idea what can I do. There are probably other easier and more optimal ways to do it, but as I said the academy expect an answer from us using the "basic" knowledge we have at this point. However, every approach will be a huge help.

3

There are 3 best solutions below

0
Nuradil Zhanadil uulu On BEST ANSWER

You can create while loop, which will be working until user enters word 'EXIT'. Inside We can use HashMap for counting the occurrence of each word. In this example, your code is more dynamic, and can handle as many words entered.

// Creating while loop to be able to loop, until we get word EXIT from user
OUTER:
while (true){
    System.out.println("Please enter 3 words separated by space");
    // This way we can get all 3 words once, and store inside a String array
    String[] words = scanner.nextLine().split(" ");
    
    // Creating Hashmap counter where will be storing occurrence of each word
    HashMap<String, Integer> counter = new HashMap<>();

    // Looping Through the words
    for(String word : words){
        word = word.toLowerCase();
        
        // if One of the words is 'exit', we finish our program
        if(word.equals("exit")){
            System.out.println("Finishing the Program!");
            break OUTER;
        }
        // if counter contains this word, we increase its occurrence by 1
        if(counter.containsKey(word)){
            counter.put(word, counter.get(word)+1);
        }
        // if not, its just 1
        else {
            counter.put(word, 1);
        }
    }
    System.out.println(counter);
}
0
WJS On

Since you are only entering three words, you don't really need an array or any loops for this.

  • read each word into three variables.

  • Compare word1 to word2.

  • if equal, assign one to sameWord and increment the count

  • compare word3 to sameWord, if equal, they must all be equal since sameWord would only be set to a word if the previous conditional succeeded.

  • else compare word3 to word1 and word2, if either are equal, then there are two matches so increment the count. Remember, the previous count was not incremented.

  • then just print the results.


Scanner scan = new Scanner(System.in);
int sameCount = 1;
String sameWord = "@";
String word1 = scan.next().toLowerCase();
String word2 = scan.next().toLowerCase();
String word3 = scan.next().toLowerCase();
if (word1.equals(word2)) {
    sameCount++;
    sameWord = word1;

}
if (word3.equals(sameWord)) {
    sameCount++;
} else if (word3.equals(word1) || word3.equals(word2)) {
    sameWord = word3;
    sameCount++;
}

if (sameCount > 1) {
    System.out.printf("%d words were the same.%n", sameCount);
    System.out.printf("The word was '%s'%n", sameWord);
} else {
    System.out.println("None of the words were the same");
}
0
WJS On

I did not use sets, maps, or other classes since you said you only had three words. No more or less. So I figured the exit wasn't required either. But here are a couple of stream solutions you may be interested in. The first shows all counts for each word. The second eliminates words that had no duplicates.

  • Use stream to continue taking input from the scanner.
  • Using takeWhile, continue to put the elements on the stream until 'exit' is entered.
  • Using groupingBy, create a map to use the word as a key, The value will be incremented for each occurrence of that word using counting.

Then the entries are printed to show each word and its count.

Scanner input = new Scanner(System.in);
System.out.println("Enter values. Type 'exit' to quit");
Map<String, Long> wordCounts = Stream.generate(() ->
         input.next().toLowerCase())
        .takeWhile(str -> !str.equals("exit"))
        .collect(Collectors.groupingBy(word -> word,
                Collectors.counting()));

wordCounts.entrySet().forEach(System.out::println);

for input of one two three three four four four five five six seven eight nine nine exit prints

nine=2
six=1
four=3
one=1
seven=1
five=2
three=2
two=1
eight=1

This next example is exactly the same except for using collectingAndThen which allows post processing of the map. In this case words that only occurred once were removed from the map.

Map<String, Long> dupsOnly = Stream.generate(() -> 
         input.next().toLowerCase())
        .takeWhile(str -> !str.equals("exit"))
        .collect(Collectors.collectingAndThen(
                Collectors.groupingBy(word -> word,
                        Collectors.counting()),
                map -> {
                         map.values().removeIf(count -> count == 1);
                         return map;
                }));
dupsOnly.entrySet().forEach(System.out::println);

For the same input as above, prints

nine=2
four=3
five=2
three=2

Note: if you already have your words (including exit) in an array, you can do the following:

Arrays.stream(wordArray).takeWhile(...