【问题标题】:Detecting if a character is a letter检测字符是否为字母
【发布时间】:2012-05-29 07:04:25
【问题描述】:

给定一组单词,我需要将它们放在以单词的第一个字母为键的散列中。 我有单词 = {},键 A..Z 和 0 表示数字和符号。 我正在做类似的事情

var firstLetter = name.charAt(0);
    firstLetter = firstLetter.toUpperCase();

if (firstLetter < "A" || firstLetter > "Z") {
    firstLetter = "0";
}
if (words[firstLetter] === undefined) {
    words[firstLetter] = [];
} 
words[firstLetter].push(name);

但这会因分词和其他字符而失败,例如在单词 Ärzteversorgung 中。 那个词放在“0”数组里,我怎么把它放在“A”数组里?

【问题讨论】:

  • 您只想将 Ä 之类的字符检测为字母,还是将 Ä 视为 A 检测?
  • Ä 不是 A。您需要将带重音的字符映射到不带重音的字符。
  • 您还必须映射 Ä 和该字符的其他字母。就像您为 0 1 2 3 ..... 和 abc 等所做的那样。
  • 是否适合使用正则表达式测试,例如/[\w\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]/.test(firstLetter)

标签: javascript utf-8 character-encoding


【解决方案1】:

您可以使用它来测试一个字符是否可能是一个字母:

var firstLetter = name.charAt(0).toUpperCase();
if( firstLetter.toLowerCase() != firstLetter) {
    // it's a letter
}
else {
    // it's a symbol
}

这是可行的,因为 JavaScript 已经有一个小写到大写字母的映射(反之亦然),所以如果一个字符没有被toLowerCase() 改变,那么它就不在字母表中。

【讨论】:

  • 一个有趣的技巧,但正如您所强调的,它只是“可能”起作用。但是,如果您为所有可能出现的字符添加临时检查并在简单测试中导致错误结果,则可能会使用它。在拉丁语 1 范围内,以下字符被错误分类:º 和 ª(阳性和阴性序数指示符)、尖锐的 ß(可能是这里最相关的字符),以及有争议的微符号 µ(在 Unicode 中的正式字母,兼容性相当于希腊字母 mu,但被广泛理解为特殊字符而不是字母)。
  • 它只适用于两院制脚本中的字符,即区分大小写的书写系统;大多数脚本没有(例如,希伯来语、梵文、中文)。
  • @JukkaK.Korpela - 是的,有缺点,优点是检查的速度。这可以比其他任何东西处理得更快,并且英语可能(应该)是大多数人需要的唯一语言)
  • @vsync,问题提到了示例词“Ärzteversorgung”。这不是英语。通常,如果人们只想到英语,他们甚至不会问这个问题——他们只是假设[A-Za-z] 涵盖了所有字母。
  • Stackoverflow 中的问题有时毫无意义,因为我是从谷歌来到这里的,而 OP 所要求的并不是标题所暗示的,因此为那些从谷歌来到这里的人提供答案很重要答案。
【解决方案2】:

您可以使用.charCodeAt(0); 获取 ASCII 图表中的位置,然后进行一些检查。

您要查找的范围可能是 65-90、97-122、128-154、160-165(含),但请通过查看 ASCII Chart 仔细检查这一点

类似的东西

if((x>64&&x<91)||(x>96&&x<123)||(x>127&&x<155)||(x>159&&x<166))

x 是字符代码

【讨论】:

  • 我不知道,charCodeAt MDN“Unicode 代码点范围从 0 到 1,114,111”
  • @jnrbsn 不,它不会... ASCII 不能涵盖所有被认为是每种语言的字母的所有内容
  • @ajax333221 有一些有效的代码点不是可打印字符
【解决方案3】:

您可以使用正则表达式。不幸的是,JavaScript 不认为国际字符是“单词字符”。但是你可以用下面的正则表达式来做到这一点:

var firstLetter = name.charAt(0);
firstLetter = firstLetter.toUpperCase();
if (!firstLetter.match(/^\wÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜäëïöüçÇߨøÅ寿ÞþÐð$/)) {
    firstLetter = "0";
}
if (words[firstLetter] === undefined) {
    words[firstLetter] = [];
} 
words[firstLetter].push(name);

【讨论】:

    【解决方案4】:

    尝试将字符转换为大写和小写,并检查是否有区别。只有字母字符在转换为各自的大小写时会发生变化(数字、标点符号等不会)。下面是一个使用这个概念的示例函数:

    function isALetter(charVal)
    {
        if( charVal.toUpperCase() != charVal.toLowerCase() )
           return true;
        else
           return false;
    }
    

    【讨论】:

    • 这不起作用。表达式 "Á" == "á" 将始终返回 false!
    【解决方案5】:

    幸运的是,这在没有外部库的情况下现在是可能的。直接来自the docs

    let story = "It’s the Cheshire Cat: now I shall have somebody to talk to.";
    
    // Most explicit form
    story.match(/\p{General_Category=Letter}/gu);
    
    // It is not mandatory to use the property name for General categories
    story.match(/\p{Letter}/gu);
    

    【讨论】:

      猜你喜欢
      • 2016-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多