6

我需要取一串混合的亚洲字符(目前,假设只有中文汉字或日文汉字/平假名/片假名)和“字母​​数字”(即英文、法文),并按以下方式计算:

1) 将每个亚洲字符计为 1;2) 将每个字母数字 WORD 计为 1;

几个例子:

株式会社myCompany = 4 个字符 + 1 个单词 = 总共 5 个字符 株式会社マイコ = 7 个字符


到目前为止,我唯一的想法是使用:

var wordArray=val.split(/\w+/);

然后检查每个元素以查看其内容是否为字母数字(因此计为 1)或不是(因此取数组长度)。但我不觉得这真的很聪明,被计算的文本可能高达 10,000 字,所以不是很快。

想法?

4

3 回答 3

3

不幸的是,JavaScriptRegExp不支持 Unicode 字符类。\w仅适用于 ASCII 字符(以一些浏览器错误为模)。

但是,您可以在组中使用 Unicode 字符,因此如果您可以将您感兴趣的每组字符隔离为一个范围,您就可以做到这一点。例如。:

var r= new RegExp(
    '[A-Za-z0-9_\]+|'+                             // ASCII letters (no accents)
    '[\u3040-\u309F]+|'+                           // Hiragana
    '[\u30A0-\u30FF]+|'+                           // Katakana
    '[\u4E00-\u9FFF\uF900-\uFAFF\u3400-\u4DBF]',   // Single CJK ideographs
'g');

var nwords= str.match(r).length;

(这试图为日语提供更真实的“单词”计数,将一种假名的每次运行都计算为一个单词。当然,这仍然不对,但它可能比将每个音节视为一个单词更接近。)

显然,如果你想“正确地做”,还有更多的角色需要考虑。让我们希望你没有基本的多语言平面之外的字符,例如!

于 2010-02-23T02:06:48.173 回答
-1

您可以遍历文本中的每个字符,检查每个字符以查找断字。以下示例执行此操作,将每个中文/日文/韩文 (CJK) 表意文字计为一个单词,并将所有字母数字字符串视为单个单词。

关于我的实现的一些注意事项:

  1. 它可能无法正确处理重音字符。他们可能会触发断词。您可以修改wordBreakRegEx来解决此问题。

  2. cjkRegEx不包括一些更深奥的代码点范围,因为它们需要 5 个十六进制数字来引用,而 JavaScript 的正则表达式引擎似乎不允许您这样做。但是您可能不需要担心这些,因为我什至认为大多数字体都不包含它们。

  3. 我故意将日文平假名和片假名排除在外cjkRegEx,因为我不确定你想如何处理这些。根据您正在处理的文本类型,将它们的字符串视为单个单词可能更有意义。在这种情况下,您需要添加逻辑来识别“假名单词”与“字母数字单词”的区别。如果您不在乎,那么您只需将它们的代码点范围添加到cjkRegEx. 当然,您可以尝试识别假名字符串中的分词,但这很快就会变得非常困难。

示例实现:

function getWordCount(text) {
  // This matches all CJK ideographs.
  var cjkRegEx = /[\u3400-\u4db5\u4e00-\u9fa5\uf900-\ufa2d]/;

  // This matches all characters that "break up" words.
  var wordBreakRegEx = /\W/;

  var wordCount = 0;
  var inWord = false;
  var length = text.length;
  for (var i = 0; i < length; i++) {
    var curChar = text.charAt(i);
    if (cjkRegEx.test(curChar)) {
      // Character is a CJK ideograph.
      // Count it as a word.
      wordCount += inWord ? 2 : 1;
      inWord = false;
    } else if (wordBreakRegEx.test(curChar)) {
      // Character is a "word-breaking" character.
      // If a word was started, increment the word count.
      if (inWord) {
        wordCount += 1;
        inWord = false;
    } else {
      // All other characters are "word" characters.
      // Indicate that a word has begun.
      inWord = true;
    }
  }

  // If the text ended while in a word, make sure to count it.
  if (inWord) {
    wordCount += 1;
  }

  return wordCount;
}

Unihan 数据库对于学习 unicode 中的 CJK 非常有帮助。当然,Unicode 主页也有大量信息。

于 2010-02-23T01:58:29.477 回答
-2

我认为您想遍历所有字符,并在每次当前字符与前一个字符使用不同的单词(根据您的定义)时增加一个计数器。

于 2010-02-23T01:14:15.503 回答