在javascript中将单词拆分为音节

Posted

技术标签:

【中文标题】在javascript中将单词拆分为音节【英文标题】:Splitting word into syllables in javascript 【发布时间】:2018-08-30 09:26:01 【问题描述】:

我的目的是构建一个简单的过程,通过它我可以将单词分成音节。方法是在元音出现时拆分单词。但是,问题是当辅音后面没有元音时,在这种情况下会在该辅音处发生分裂。

我的测试用例如下:

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

在第一个例子中,头发是一个音节,因为最后的辅音后面没有元音,同样,在最后一个例子中,“t”后面跟着一个 r,因此应该将“ha”视为一个音节. 在第二个例子中,ai 被认为是一个元音,所以 hai 将成为一个音节。

更多示例包括

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

请注意,我使用的是简单的例子,因为英语语言在声音方面非常复杂

我的代码如下

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')

但是,我的代码甚至不返回字符串。我做错了什么?

【问题讨论】:

你在 for 循环中有 var st = ''; 我对你的例子有点困惑。你能解释一下你想要达到的目标吗? syllabificate的逻辑是什么?请先说明您的方法。 @gurvinder372 我怀疑这是问题之一,但逻辑也有偏差。因此要求澄清 描述fatherhatred之间的区别。为什么一个 'fa'+'ther' 和另一个 'hat'+'red' 使用你的辅音元音方法 【参考方案1】:

您当前方法的问题

你的代码有很多问题:

循环中的第一件事,您将st 设置为一个空字符串。这意味着您永远不会积累任何信件。您可能想要上面的那一行,循环之外。 您正在尝试使用i in input 循环遍历字母的索引。在 javascript 中,in 关键字将对象的键作为字符串提供给您。所以你得到的是字符串,而不是数字,以及在字符串上定义的一些方法的名称。请改用var i = 0; i < input.length; i++。 也许不是问题的直接原因,但仍然 - 您的代码很混乱。这些怎么样? 使用更清晰的名称。 currentSyllable 代替 stsyllables 代替 arrs 等等。 不要使用嵌套的if - else,而是使用一个if - else if - else。 您重复检查元音两次的相同代码。而是将其拆分为函数isVowel(letter)

一种新方法

使用regular expressions!这是您对用正则表达式表示的音节的定义:

第一,零个或多个辅音:[^aeiouy]* 然后,一个或多个元音:[aeiouy]+ 之后,零或以下之一: 辅音,后跟词尾:[^aeiouy]*$ 辅音(如果后面跟着另一个辅音):[^aeiouy](?=[^aeiouy])

综合起来你得到这个:

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

您可以在here 中看到它。要在 JavaScript 中运行它,请使用 match 函数:

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))

请注意,这不适用于没有元音的单词。您要么必须修改正则表达式以适应这种情况,要么做一些其他解决方法。

【讨论】:

希望您不介意,我更新了示例并使其更加健壮。真的很喜欢这种正则表达式方法,非常棒! 我还没有时间深入研究修复它(抱歉),但是这个正则表达式实现对于大多数事情来说可能很接近,但并不完全正确。 “火”(单音节)只是一个例子。我怀疑这与以元音结尾的单词有关? @DylanWatson 我尝试使用您在问题中概述的音节定义。但是我认为您不能仅根据辅音和元音来定义音节,您需要了解发音。 “火”和“婴儿”的辅音和元音相同,但一个有一个音节,另一个有两个。教计算机区分这些并非易事。【参考方案2】:

我在 RegEx 方面很弱,虽然 Anders 的示例大部分时间都是正确的,但我确实发现了一些例外情况。这是我到目前为止发现的工作(但我确信还有其他我还没有发现的例外)。我相信艺术大师可以对其进行RegEx'ified。该函数返回一个音节数组。

        function getSyllables(word)
        var response = [];
        var isSpecialCase = false;
        var nums = (word.match(/[aeiou]/gi) || []).length;
        //debugger;
        if (isSpecialCase == false && (word.match(/[0123456789]/gi) || []).length == word.length )
            // has digits
            response.push(word);
            isSpecialCase = true;
        

        if (isSpecialCase == false && word.length < 4)
            // three letters or less
            response.push(word);
            isSpecialCase = true;
         

        if (isSpecialCase == false && word.charAt(word.length-1) == "e")
            if (isVowel(word.charAt(word.length-2)) == false)
                var cnt = (word.match(/[aeiou]/gi) || []).length;
                if (cnt == 3)
                    if (hasDoubleVowels(word))
                        // words like "piece, fleece, grease"
                        response.push(word);
                        isSpecialCase = true;
                    
                
                if (cnt == 2)
                    // words like "phase, phrase, blaze, name", 
                    if (hasRecurringConsonant(word) == false) 
                    // but not like "syllable"
                    response.push(word);
                    isSpecialCase = true;
                    

                                    
            
        

        if (isSpecialCase == false)
            const syllableRegex = /[^aeiouy]*[aeiouy]+(?:[^aeiouy]*$|[^aeiouy](?=[^aeiouy]))?/gi;
            response = word.match(syllableRegex);
        

        return response;
     

【讨论】:

ReferenceError: isVowel is not defined

以上是关于在javascript中将单词拆分为音节的主要内容,如果未能解决你的问题,请参考以下文章

如何在 BigQuery SQL 中将字符串列拆分为多行单个单词和单词对?

如何在Python中将具有名称(1个或多个单词)和数字的单行输入字符串拆分为[“名称”,“数字”]?

华为OD机试真题Java实现相对开音节真题+解题思路+代码(2022&2023)

如何在 bash shell 中将一个字符串拆分为多个字符串,至少用一个空格分隔?

如何在 JavaScript 中将长正则表达式拆分为多行?

在Javascript中将PDF拆分为单独的文件