2012-02-16 111 views
4

我需要使用Javascript来搜索首字母(不确定这是不是正确的名称,如果不是,请改变问题)。例如:使用主题"Abraham Maslow"将返回true,并搜索"John""Johnathan Smith"也将是true在JavaScript中优化缩写搜索

搜索"mas"。但是,在"Marygold Ding"上搜索"gold"将是false

我最初以为的:

function search(initial, subjectsArray) { 
    var result = []; 
    var tmp = null; 
    var initialLowercase = initial.toLowerCase(); 
    for (var i = 0; i < subjectsArray.length; i++) { 
     tmp = subjectsArray[i].toLowerCase(); 
     if (tmp.startsWith(initialLowercase) 
       || tmp.indexOf(' ' + initialLowercase) != -1) { 
      result.push(subjectsArray[i]); 
     } 
    } 
    return result; 
} 

如何优化这个代码?

+0

所以,基本上,你有一个名字(或名称列表),你想检查某个子字符串是否是名字或姓氏的开始?首字母缩写不是正确的词,但我也想不出一个更好的词。你可以对格式做出什么保证? – 2012-02-16 11:58:57

+0

缩略语? :) – Joe 2012-02-16 11:59:53

+0

@AnthonyGrist主题的格式?它们将是任何包含一个或多个空格的字符串列表......例如,其中一个名称将只是“卡尔森”,而另一个名称则是“John Ronald Reuel Tolkien”。 – RedDragon 2012-02-16 12:01:25

回答

3

好像你想用“单词边界”在不区分大小写的正则表达式匹配,例如:

/\bmas/i.test("Abraham Maslow") === true

/\bJohn/i.test("Johnathan Smith") === true

/\bgold/i.test("Marygold Ding") === false

\b将匹配一个单词的开头或结尾,并i在正则表达式的结束使得它不区分大小写,这样mas可以匹配Maslow

- 更新:

如果字符串包含重音字符时,\ B就匹配他们,即使我们认为他们是字的一部分。在要使用(^|\s)代替这种情况下,要匹配 “字符串的开始或一些空白”:

/(^|\s)c/i.test('Drácule Smith') === false

/(^|\s)dr/i.test('Drácule Smith') === true

/(^|\s)smi/i.test('Drácule Smith') === true

MDN regex documentation

+1

这不适用于'(/\bc/i).test("DráculeSmith“)':-( – RedDragon 2012-02-16 12:25:40

+0

因为”单词边界“只考虑az,AZ,0-9是单词 - 字符,我会更新我的答案 – 2012-02-16 12:27:45

2

为什么不使用RegExp呢?

string.search(new RegExp('\\b' + word + '\S*', 'i')) !== -1 

编辑通过@ user24建立与相同的API OP功能是:

function search(initial, subjectsArray) { 
    // Create regex for initial 
    var regex = new RegExp('\\b' + initial + '\S*', 'i'); 
    // Find subjects which contain this substring 
    for (var i = 0; i < subjectsArray.length; i++) { 
    if(subjectsArray[i].search(regex) !== -1) { 
     return true; 
    } 
    } 

    return false; 
} 
+1

这在以下情况下不起作用:''DráculeSmith'.search(new RegExp('\\ b'+'c'+'\ S *','i'))!== -1)' :-( – RedDragon 2012-02-16 12:16:54

0

正则表达式的替代方法是,您可以单独存储名称的字母,并在每个级别都包含匹配该值的“匹配”元素(应该相当快,但如果您有大量的的名字,阵列将是巨大的)。

array 
| - m 
| - matches 
| - - 'Abraham Maslow' 
| - - 'John Motson' 
| - a 
| - - matches 
| - - - 'Abraham Maslow' 
| - - s 
| - - - matches 
| - - - 'Abraham Maslow' 
| - - - l 
| - - - - matches 
| - - - - - 'Abraham Maslow' 
... 
| - s 
| - - matches 
| - - 'Johnathan Smith' 
| - - m 
| - - - matches 
| - - - - 'Johnathan Smith' 
| - - - - i 

这应该速度相当不错的优化,因为你可以做这样的事情来查找一个名字:

​​

这样,你永远不会下降,这具有其他任何一个分支而不是你感兴趣的,所以当名字不是以“S”开头的时候你永远不会考虑“Johnathan Smith”,并且当名字以“Ma”开头而不是“Mo”时,永远不会考虑“John Motson”等

1

不能你只是<start of input or whitespace>Token

(/(^|\s)Drá/i).test("Dráculezz Smith")