Java >> Java tutorial >  >> Java

Hvordan man beregner stavelser i tekst med regex og Java

Dette spørgsmål er fra et Java-kursus fra UCSD, har jeg ret?

Jeg synes, du skal give nok oplysninger til dette spørgsmål, så det ikke vil forvirre folk, der ønsker at tilbyde noget hjælp. Og her har jeg min egen løsning, som allerede er testet af testcasen fra det lokale program, også OJ fra UCSD.

Du gik glip af nogle vigtige oplysninger om definitionen af ​​stavelse i dette spørgsmål. Jeg tror faktisk, at hovedpunktet i dette problem er, hvordan du skal håndtere e . Lad os f.eks. sige, at der er en kombination af te . Og hvis du sætter te midt i et ord skal det selvfølgelig tælles som en stavelse; Men hvis det er i slutningen af ​​et ord, er e skal opfattes som en silent e på engelsk, så det skal ikke opfattes som en stavelse.

Det er det. Og jeg vil gerne skrive min tanke ned med noget pseudokode:

  if(last character is e) {
        if(it is silent e at the end of this word) {
           remove the  silent e;
           count the rest part as regular;
        } else {
           count++;
  } else {
        count it as regular;
  }
}

Du vil muligvis opdage, at Jeg bruger ikke kun regulært udtryk at håndtere dette problem. Faktisk har jeg tænkt over det:kan dette spørgsmål virkelig kun udføres ved hjælp af regex? Mit svar er:nej, det tror jeg ikke. I det mindste nu, med den viden UCSD giver os, er det for svært at gøre det. Regex er et kraftfuldt værktøj, det kan kortlægge de ønskede karakterer meget hurtigt. Regex mangler dog noget funktionalitet. Tag te som eksempel igen, vil regex ikke være i stand til at tænke to gange, når det står over for ordet som teate (Jeg fandt på dette ord bare for eksempel). Hvis vores regex-mønster ville tælle de første te som stavelse, så hvorfor den sidste te ikke?

I mellemtiden har UCSD faktisk talt om det på opgavepapiret:

Hvis du finder dig selv i at lave mental gymnastik for at finde på et enkelt regex til at tælle stavelser direkte, er det normalt en indikation af, at der er en enklere løsning (tip:overvej en løkke over tegn - se næste tip nedenfor). Bare fordi et stykke kode (f.eks. et regulært udtryk) er kortere, betyder det ikke, at det altid er bedre.

Hint her er, at du bør tænke dette problem sammen med noget loop, kombineret med regex.

OK, jeg skulle endelig vise min kode nu:

protected int countSyllables(String word)
{
    // TODO: Implement this method so that you can call it from the 
    // getNumSyllables method in BasicDocument (module 1) and 
    // EfficientDocument (module 2).
    int count = 0;
    word = word.toLowerCase();

    if (word.charAt(word.length()-1) == 'e') {
        if (silente(word)){
            String newword = word.substring(0, word.length()-1);
            count = count + countit(newword);
        } else {
            count++;
        }
    } else {
        count = count + countit(word);
    }
    return count;
}

private int countit(String word) {
    int count = 0;
    Pattern splitter = Pattern.compile("[^aeiouy]*[aeiouy]+");
    Matcher m = splitter.matcher(word);

    while (m.find()) {
        count++;
    }
    return count;
}

private boolean silente(String word) {
    word = word.substring(0, word.length()-1);

    Pattern yup = Pattern.compile("[aeiouy]");
    Matcher m = yup.matcher(word);

    if (m.find()) {
        return true;
    } else
        return false;
}

Du kan finde det udover den givne metode countSyllables , opretter jeg også to yderligere metoder countit og silente . countit er til at tælle stavelserne inde i ordet, silente forsøger at finde ud af, at dette ord slutter med en tavs e . Og det skal også bemærkes, at definitionen af ​​not silent e . For eksempel the bør overveje not silent e , mens ate betragtes som silent e .

Og her er status, min kode har allerede bestået testen, fra både lokal testcase og OJ fra UCSD:

Og fra OJ testresultatet:

P.S:Det burde være fint at bruge noget som [^aeiouy] direkte, fordi ordet er parset, før vi kalder denne metode. Det er også nødvendigt at skifte til små bogstaver, det ville spare en masse arbejde med at håndtere de store bogstaver. Det, vi ønsker, er kun antallet af stavelser. Når vi taler om tal, er en elegant måde at definere count som statisk, så den private metode kunne direkte bruge count++ inde. Men nu er det fint.

Du er velkommen til at kontakte mig, hvis du stadig ikke forstår metoden til dette spørgsmål :)


Ved at bruge konceptet bruger5500105 har jeg udviklet følgende metode til at beregne antallet af stavelser i et ord. Reglerne er:

  • på hinanden følgende vokaler tælles som 1 stavelse. for eksempel. "ae" "ou" er 1 stavelse

  • Y betragtes som en vokal

  • e i slutningen tælles som stavelse, hvis e er den eneste vokal:fx:"den" er en stavelse, da "e" i slutningen er den eneste vokal, mens "der" også er 1 stavelse, fordi "e" er ved ende, og der er en anden vokal i ordet.

     public int countSyllables(String word) {
         ArrayList<String> tokens = new ArrayList<String>();
         String regexp = "[bcdfghjklmnpqrstvwxz]*[aeiouy]+[bcdfghjklmnpqrstvwxz]*";
         Pattern p = Pattern.compile(regexp);
         Matcher m = p.matcher(word.toLowerCase());
    
    
         while (m.find()) {
             tokens.add(m.group());
         }
    
     //check if e is at last and e is not the only vowel or not
         if( tokens.size() > 1 && tokens.get(tokens.size()-1).equals("e")  )
             return tokens.size()-1; // e is at last and not the only vowel so total syllable -1 
         return tokens.size(); 
     }
    

Dette giver dig en række stavelser vokaler i et ord:

public int getNumVowels(String word) {

    String regexp = "[bcdfghjklmnpqrstvwxz]*[aeiouy]+[bcdfghjklmnpqrstvwxz]*";
    Pattern p = Pattern.compile(regexp);
    Matcher m = p.matcher(word.toLowerCase());

    int count = 0;

    while (m.find()) {
        count++;
    }
    return count;
}

Du kan kalde det på hvert ord i din strengmatrix:

    String[] words = getText().split("\\s+");
    for (String word : words ) {
      System.out.println("Word: " + word + ", vowels: " + getNumVowels(word));
    }

Opdatering: som freerunner bemærkede, er det mere kompliceret at beregne antallet af stavelser end blot at tælle vokaler. Man skal tage højde for kombinationer som du , ui , oo , den sidste stille e og muligvis noget andet. Da jeg ikke har engelsk som modersmål, er jeg ikke sikker på, hvad den korrekte algoritme ville være.


Java tag