我在这里使用Dylan's question关于JavaScript音节计数,更具体地说artfulhacker's answer,在我自己的代码中,无论我提供哪个单字或多字字符串,该函数始终能够正确计算音节数。
我对RegEx的经验有限,并且没有足够的先验知识来解释以下代码中究竟发生了什么,没有一些帮助。我并不是一个对我从某个地方工作的代码感到高兴的人,而我却不知道 它是如何运作的。有人能够在下面的new_count(word)
函数中详细说明发生了什么,并帮助我破译RegEx的使用以及该函数如何能够正确计算音节?很多
function new_count(word) {
word = word.toLowerCase(); //word.downcase!
if(word.length <= 3) { return 1; } //return 1 if word.length <= 3
word = word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, ''); //word.sub!(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '')
word = word.replace(/^y/, ''); //word.sub!(/^y/, '')
return word.match(/[aeiouy]{1,2}/g).length; //word.scan(/[aeiouy]{1,2}/).size
}
答案 0 :(得分:3)
/(?:[^laeiouy]es|ed|[^laeiouy]e)$/
匹配三个可能的子串:除“l”之外的字母或后跟“es”的元音(如“res”或“tes”); “编”;或非元音,非'''后跟“e”。由于模式末尾的$
,这些模式必须出现在要匹配的单词的末尾。分组(?: )
只是一个分组;领先的?:
做出了这种区分。模式本来可以短一些:
/(?:[^laeiouy]es?|ed)$/
会做同样的事情。在任何情况下,如果模式匹配,则从单词中删除所涉及的字符。
然后,
/^y/
匹配单词开头的'y'。如果找到“y”,则将其删除。
最后,
/[aeiouy]{1,2}/g
匹配任何一个或两个字符的元音(包括'y')。 g
后缀使其成为全局匹配,因此返回值是一个由所有此类元音跨度组成的数组。返回数组的长度是音节数(根据这种技术)。
请注意,“诗”和“狮子”这两个词会被报告为单音节词,这对于某些英语变体可能是正确的,但不是全部。
Here is a pretty good reference for JavaScript regular expression operators.
答案 1 :(得分:3)
据我所知,我们基本上想用一些特殊情况来计算元音或元音对。让我们从最后一行开始,这样做,即计算元音和对:
return word.match(/[aeiouy]{1,2}/g).length;
这将匹配任何元音或元音对。 [...]
表示character class,即如果我们逐个字符地查看字符串,则如果实际字符是其中之一,则匹配。 {1, 2}
是repetitions的数量,即它意味着我们应该恰好匹配一个或两个这样的字符。
另外两行是针对特殊情况的。
word = word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '');
这一行将删除&#39; syllables&#39;从这个词的结尾,它们是:
(我不确定这背后的语法含义是什么,但我想,这个词的结尾处有&#39;音节,就像&#39; -ed& #39;,&#39; -ded&#39;,&#39; -xed&#39;等等,实际上并非如此。)
至于正则表达式部分:(?:...)
是non-capturing group。我想在这种情况下,这个群体非捕获并不重要;这只是意味着我们想要对整个表达式进行分组,但是我们不需要再参考它。但是,我们也可以使用捕获组(即(...)
)
[^...]
是一个否定的字符类。这意味着,匹配任何字符,这些都不是这里列出的。 (与上面提到的(非否定的)字符类比较。)
管道符号,即|
,是alternation运算符,这意味着任何表达式都可以匹配。
最后,$
锚点匹配end of the line或字符串(取决于上下文)。
word = word.replace(/^y/, '');
此行从单词的开头删除了&#39; -s(可能&#39; y&#39;在开头不算作音节 - 这在我看来是有意义的)。
^
是匹配the beginning of the line或上述字符串(c.f。$
)的锚点。
注意:只有当word
真正包含一个单词时,该算法才有效。