Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Splitting word into syllables in javascript

My intention is to build a simple process with which I can split the word into syllables. The approach is to split the word whenever the vowel occurs. However, the trouble is when a consonant is not followed by a vowel, in such a case the split occurs at that consonant.

My test cases are as follows:

hair = ["hair"]
hairai = ["hai", "rai"]
hatred = ["hat", "red"]

In the first example hair is one syllable, as the final consonant is not followed by a vowel, similarly, in the final example, the "t" is followed by an r and so should considered along "ha" as one syllable. In the second example, ai is considered as one vowel sound and so hai will become one syllable.

More examples include

father = ["fat", "her"]
kid = ["kid"]
lady = ["la","dy"]

Please note that, I am using simplistic examples as the ENglish language is quite complex when it comes to sound

My code is as follows

function syllabify(input) {
  var arrs = [];
  for (var i in input) {
    var st = '';
    var curr = input[i];
    var nxt = input[i + 1];
    if ((curr == 'a') || (curr == 'e') || (curr == 'i') || (curr == 'o') || (curr == 'u')) {
      st += curr;
    } else {
      if ((nxt == 'a') || (nxt == 'e') || (nxt == 'i') || (nxt == 'o') || (nxt == 'u')) {
        st += nxt;
      } else {
        arrs.push(st);
        st = '';
      }
    }
  }
  console.log(arrs);
}

syllabify('hatred')

However, my code does not even return the strings. What am I doing wrong?

like image 541
virupaksha Avatar asked Apr 25 '26 04:04

virupaksha


1 Answers

Problems with your current approach

There are a number of problems with your code:

  • First thing in the loop, you set st to an empty string. This means that you never accumulate any letters. You probably want that line above, outside the loop.
  • You are trying to loop over the indexes of letters by using i in input. In JavaScript, the in keyword gives you the keys of an object as strings. So you get strings, not numbers, plus the names of some methods defined on strings. Try var i = 0; i < input.length; i++ instead.
  • Maybe not the direct cause of the problems, but still - your code is messy. How about these?
    • Use clearer names. currentSyllable instead of st, syllables instead of arrs and so on.
    • Instead of a nested if - else, use one if - else if - else.
    • You repeat the same code that checks for vowels twice. Separate it into a function isVowel(letter) instead.

A new approach

Use regular expressions! Here is your definition of a syllable expressed in regex:

  • First, zero or more consonants: [^aeiouy]*
  • Then, one or more vowels: [aeiouy]+
  • After that, zero or one of the following:
    • Consonants, followed by the end of the word: [^aeiouy]*$
    • A consonant (if it is followed by another consonant): [^aeiouy](?=[^aeiouy])

Taken together you get this:

/[^aeiouy]*[aeiouy]+(?:[^aeiouy]*$|[^aeiouy](?=[^aeiouy]))?/gi

You can see it in action here. To run it in JavaScript, use the match function:

const syllableRegex = /[^aeiouy]*[aeiouy]+(?:[^aeiouy]*$|[^aeiouy](?=[^aeiouy]))?/gi;

function syllabify(words) {
    return words.match(syllableRegex);
}

console.log(['away', 'hair', 'halter', 'hairspray', 'father', 'lady', 'kid'].map(syllabify))

Note that this does not work for words without vowels. You would either have to modify the regex to accomodate for that case, or do some other workaround.

like image 168
Anders Avatar answered Apr 26 '26 19:04

Anders



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!