Home > front end >  To classify letters in words as vowels and consonants
To classify letters in words as vowels and consonants

Time:03-31

Given a word, I need a function that returns the structure of the word in terms of vowels and consonants. "c" stands for consonants and "v" for vowels. If the letter "y" is the first letter of a word, it is a consonant, otherwise, it considered a vowel. For example, wordClass("dance") returns "cvccv" and wordClass("yucky") returns "cvccv".

I tried this but there is probably a more efficient way to do this:

Function wordClass(word As String) As String
    Dim vowels(1 To 6) As String, vowelsNoY(1 To 5) As String, consonants(1 To 22) As String, pattern(1 To 5) As String
    Dim i As Integer, j As Integer
    
    vowels(1) = "a"
    vowels(2) = "e"
    vowels(3) = "i"
    vowels(4) = "o"
    vowels(5) = "u"
    vowels(6) = "y"
    
    vowelsNoY(1) = "a"
    vowelsNoY(2) = "e"
    vowelsNoY(3) = "i"
    vowelsNoY(4) = "o"
    vowelsNoY(5) = "u"
    
    consonants(1) = "b"
    consonants(2) = "c"
    consonants(3) = "d"
    consonants(4) = "f"
    consonants(5) = "g"
    consonants(6) = "h"
    consonants(7) = "j"
    consonants(8) = "k"
    consonants(9) = "l"
    consonants(10) = "m"
    consonants(11) = "n"
    consonants(12) = "p"
    consonants(13) = "q"
    consonants(14) = "r"
    consonants(15) = "s"
    consonants(16) = "t"
    consonants(18) = "v"
    consonants(19) = "w"
    consonants(20) = "x"
    consonants(21) = "y"
    consonants(22) = "Z"
    
    For h = 1 To Len(consonants)
    
        If StrComp(Mid(word, 1, 1), vowelsNoY(h), vbTextCompare) = 0 Then
            pattern(1) = "v"
        ElseIf StrComp(Mid(word, 1, 1), consonants(h), vbTextCompare) = 0 Then
            pattern(1) = "c"
        End If
    
    Next h
        
    For i = 2 To Len(word)
        
        For j = 2 To Len(word)
            If StrComp(Mid(word, i, 1), vowels(j), vbTextCompare) = 0 Then
                pattern(j) = "v"
            ElseIf StrComp(Mid(word, i, 1), consonants(j), vbTextCompare) = 0 Then
                pattern(j) = "c"
            End If
        Next j
    Next i
            
    wordClass = CStr(pattern)
    
End Function

CodePudding user response:

I would use something like this. Copy this to a fresh module:

Public strVowels As String
Public arrVowels() As String

Public Function wordClass(strWord As String) As String

Dim lngLetter As Long

    setup
    
    For lngLetter = 1 To Len(strWord)
        If isVowel(Mid(strWord, lngLetter, 1)) Then
            wordClass = wordClass & "V"
        Else
            wordClass = wordClass & "C"
        End If
    Next lngLetter
    
End Function

Public Sub setup()

strVowels = "a;e;i;o;u"
arrVowels = Split(strVowels, ";")

End Sub

Public Function isVowel(strLetter As String)
    isVowel = Not IsError(Application.Match(LCase(strLetter), arrVowels, False))
End Function

CodePudding user response:

Option Explicit

Public Sub Example()
    Debug.Print wordClass("dance")
    Debug.Print wordClass("yucky")
End Sub


Public Function wordClass(ByVal word As String) As String
    Const vowels As String = "aeiouy"
    Const vowelsNoY As String = "aeiou"
    Const consonants As String = "bcdfghjklmnopqrstvwxyz"
    
    Dim retval As String

    Dim i As Long
    For i = 1 To Len(word)
        Dim char As String
        char = Mid$(word, i, 1)
        
        If i = 1 Then
            If InStr(vowelsNoY, char) Then
                retval = retval & "v"
            ElseIf InStr(consonants, char) Then
                retval = retval & "c"
            Else
                retval = retval & "-"
            End If
        Else
            If InStr(vowels, char) Then
                retval = retval & "v"
            ElseIf InStr(consonants, char) Then
                retval = retval & "c"
            Else
                retval = retval & "-"
            End If
        End If
    Next i
    
    wordClass = retval
End Function

CodePudding user response:

I would not define arrays, just use Instr to check if a character is within the vowels. To check for consonants, I would check that the character is not a vowel and that it is between "b" and "z" - else it is some other character.

"Efficiency" for me is mainly a matter of readability - no matter which attempt you use, everything is done in memory and unless you want to analyze millions of words, there is no need to optimize for speed.

I also check for the first character. If it is a "y", i put hardcoded that it is a Consonant and start the loop with the 2nd character.

This is my attempt:

Function wordClass(ByVal word As String) As String
    Dim i As Long, startIndex As Long
    Const vowels = "aeiouy"
    Const vowel = "V"
    Const consonant = "C"
    Const other = "?"
    
    word = LCase(word)
    If Left(word, 1) = "y" Then
        wordClass = consonant
        startIndex = 2
    Else
        wordClass = ""
        startIndex = 1
    End If
    
    For i = startIndex To Len(word)
        Dim c As String
        c = Mid(word, i, 1)
        If InStr(vowels, c) > 0 Then
            wordClass = wordClass & vowel
        ElseIf c > "a" And c <= "z" Then
            wordClass = wordClass & consonant
        Else
            wordClass = wordClass & other
        End If
    Next

End Function

CodePudding user response:

You could do this in two steps with regex. Regex can search the string for individual letters and then replace all matching letters with "c" or "v". You would have 2 patterns and 2 replacements and then it would be done.

Pattern 1 : "[bcdfghjklmnpqrstvwxz]|^y" : Matches any character in that list or a leading y.

Pattern 2 : "[aeiouy]" : Matches any character in that list

Since pattern 1 is applied first, all the remaining y's can be safely assumed to be vowel. Also, since the first pattern changes all consonants to "c", they won't match pattern 2 and be double-transformed. If you were to run the Vowel regex first and change the letters to "v", the consonant pattern would match with "v" and they would all change to "c". So the consonant replacement must happen first.

Function wordClass(word As String) As String
    Dim Consonants As Object
    Set Consonants = CreateObject("VBScript.RegExp")
    With Consonants
        .Global = True
        .MultiLine = False
        .Pattern = "[bcdfghjklmnpqrstvwxz]|^y"
    End With
    
    Dim Vowels As Object
    Set Vowels = CreateObject("VBScript.RegExp")
    With Vowels
        .Global = True
        .MultiLine = False
        .Pattern = "[aeiouy]"
    End With
    
    Dim outputString As String
    outputString = LCase(word)
    
    outputString = Consonants.Replace(outputString, "c")
    outputString = Vowels.Replace(outputString, "v")
    wordClass = outputString
End Function
  • Related