Java: make a valid REGEX

Viewed 60

i am stuck. I have a text with “And how about you, Count Peter Kirílych? If they call up the militia, you too will have to mount a horse,” remarked the old count, addressing Pierre.

so i am trying to split it and Count how often the word occurs in the text and return the results with the Max repeated to less ones. So the question how can i return results with Max repeated to less one And Some of results are wrong ,

Unfortunately my regex is not working for dash(-), (`) and quote ("). Would be glad for any help Here is what i did :

StringBuilder sb= new StringBuilder();
        Map<String, Integer> counterMap = new HashMap<>();
        for(Object str:lines){
            sb.append(str.toString()+" ");
        }
        String boom[] = sb.toString().split("['@?-` \\p{Punct}]+\\s*");
        for (String word : boom) {
            if(word.length()>=4){
            if(!word.isEmpty()) {
                word = word.trim();
                Integer count = counterMap.get(word);
                if(count == null) {
                    count = 0;
                }
                counterMap.put(word, ++count);
            }}
        }
StringBuilder bb = new StringBuilder();
        Map.Entry<String,Integer> maxEntry = null;

        for(String word : counterMap.keySet()) {
            System.out.println(word + ": " + counterMap.get(word));

            bb.append(word + " - "+counterMap.get(word)+"\n");
        }

        return bb.toString();
    }
2 Answers

Instead of trying to split your input string at word boundaries, it is easier to actually look for words - i.e. a sequence of letters. This way you can even have your regex check the length of the word.

I tried this:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

// ...

Matcher matcher = Pattern.compile("\\p{IsLatin}{4,}").matcher(sb);
while (matcher.find()) {
    String word = matcher.group();
    Integer count = counterMap.getOrDefault(word, 0);
    counterMap.put(word, ++count);
}

Here is another way to accomplish this task. Instead of splitting on all those punctuation characters...get rid of them. Clean the string so that it is nothing more than a string of words separated by a whitespaces. Split the string then find occurrences. Read the comments in code:

public static List<String> getWordOccurrences(String inputString, boolean... ignoreLetterCase) {
    boolean ignoreCase = true;              // Ignore letter case by default.
    if (ignoreLetterCase.length > 0) {      // Has otherwise been optionally supplied?
        ignoreCase = ignoreLetterCase[0];   // Let it be what was supplied.
    }
    
    // Clean the String...
    String strg = inputString.replaceAll("[\\\\@:;.-/]"," ")      // Separate joined words...
                             .replaceAll("\\s+", " ")             // Remove any extra spacing...
                             .replaceAll("[“”\\p{Punct}]+", "");  // Remove all unwanted characters...
    
    // If ignore Letter case then convert string to lower case.
    if (ignoreCase) {
        strg = strg.toLowerCase();
    }

    // Split String into a words[] String array...
    String[] words = strg.split("\\s+");
    
    Arrays.sort(words);     // Sort the Array. 

    // Creat a List<String> to store ALL word Occurrances
    List<String> occurrences = new ArrayList<>();
    
    // Determine word occurrences... 
    /* Counter to count the number of times the current 
       word in play is found within the supplied string. */
    int count;
    // Iterate through the `words[]` array...
    for (int i = 0; i < words.length; i++) {
        count = 1;  // Reset count to 1 for new word.
        /* Iterate through the `words[]` array again
           ignoring the same index as previous loop. */
        for (int j = 0; j < words.length; j++) {
            if (i != j && words[i].equals(words[j])) {
                count++; // increment counter if there is a match.
            }
        }
        
        /* Format the word string to add to the List.
           This would contain the word and the number 
           of times it was detected within the string
           separated by a single whitespace.       */
        String toAdd = words[i] + " " + count;
        
        /* Before we add the word to the list, let's 
           make sure the list doesn't already have it. */
        if (!occurrences.contains(toAdd)) {
            occurrences.add(toAdd);
        }
    }

    // In order to meet requirements:
    /* Sort the list of word occurrences in ascending order based on the 
       highest word counts first as outlined as a requirement.  A custom 
       comparator with the `Collections.sort()` method is used for this:  */
    java.util.Collections.sort(occurrences,
            (String s1, String s2) -> s2.split("\\s+")[1].compareTo(s1.split("\\s+")[1]));
    
    return occurrences;   // Return the created List.
}

To use the above method you might do something like this:

// The Input String to process...
String strg = "“And how about you, Count Peter Kirílych? If they call up the "
        + "militia, you too will have to mount a horse,” remarked the old "
        + "count, addressing Pierre.";

System.out.println(strg); // Print the input string to console:
    
// List to hold determined occurrences.
List<String> occurrences = getWordOccurrences(strg);
    
// Display the List of occurrences...
System.out.println();
System.out.println("--------------------");
System.out.println("Words (" + occurrences.size() + "):  No. of:");
System.out.println("--------------------");
for (String str : occurrences) {
    System.out.println(String.format("%-15s%-5s", 
            str.split("\\s")[0], str.split("\\s")[1]));
}
System.out.println();

And the Console Window should display something like:

“And how about you, Count Peter Kirílych? If they call up the militia, you too will have to mount a horse,” remarked the old count, addressing Pierre.

--------------------
Words (24):  No. of:
--------------------
count          2    
the            2    
you            2    
a              1    
about          1    
addressing     1    
and            1    
call           1    
have           1    
horse          1    
how            1    
if             1    
kirílych       1    
militia        1    
mount          1    
old            1    
peter          1    
pierre         1    
remarked       1    
they           1    
to             1    
too            1    
up             1    
will           1    
Related