2010-12-09 58 views
3

我想根據用戶輸入列出給定字符串中的所有trigrams(3字母單詞)。用戶可以輸入1,2或3個字符。我寫了下面的代碼:在JavaScript中列出trigrams

if (3 == trigram.length) { 
    var re = new RegExp(trigram); 
} else if (2 == trigram.length) { 
    trigram = trigram + '\\S|\\S' + trigram; 
    var re = new RegExp(trigram); 
} else if (1 == trigram.length) { 
    trigram = trigram + '\\S\\S|\\S\\S' + trigram + '|\\S' + trigram + '\\S'; 
    var re = new RegExp(trigram); 
} else { 
    alert("Trigram search pattern can be either one, two or three characters!"); 
    return null; 
} 

var re = new RegExp(trigram, "ig"); alert(re); 

trigramList = givenString.match(re); 

這只是工作的罰款,如果我有我的字符串「KDSGKHAGSKH」字符以下順序和我正在尋找由「A」我的代碼僅返回「KHA」卦在那裏我期待它返回{KHA,HAG,AGS}

回答

1

這裏有,似乎是你在找什麼

String.prototype.ngrams = function(n) { 
    var r = []; 
    for(var i = 0; i <= this.length - n; i++) 
    r.push(this.substring(i, i + n)); 
    return r; 
} 

Array.prototype.grep = function(re) { 
    var r = []; 
    for(var i = 0; i < this.length; i++) 
     if(re.test(this[i])) 
      r.push(this[i]); 
    return r; 
} 

s = "abcdefghjkl"; 
alert(s.ngrams(3).grep(/d/)) 

打印「BCD」,「CDE」兩個簡單的功能,「 DEF」。不是最高效但簡單的。

+0

嗨stereofrog,這是非常簡單和作品的n'grams。有沒有辦法改變我的代碼工作? – Srujan 2010-12-09 11:04:39

+0

我試圖使用你的方法,它工作正常。當我編輯只列出包含(A-Z)的單詞時,它不會列出n = 2格式爲「CC」的單詞。然而,它適用於n = 3,並列出了格式爲「CCC」的字符串。 – Srujan 2010-12-11 18:18:47

1

原文的問題在於,正則表達式將成功匹配的結束處設置爲下一場比賽開始的位置,這意味着您無法輕鬆獲得重疊比賽。您需要找到一種方法來使匹配字符串的長度只有一個字符,以便起始索引始終比先前成功匹配的起始索引多一個。您可以通過積極向前的方式來做到這一點,並使用捕獲組來獲取與前瞻相匹配的任何內容。

var onegram = /A(?=(\S\S))|\S(?=(\SA))|\S(?=(A\S))/ig; 
var str = 'KDSGKHAGSKH'; 
var match 
var ngrams = []; 
while ((match = onegram.exec(str)) != null) { 
    ngrams.push(match.join('')); 
} 

您可以產生一個額外的方法對字符串的幫助下,RE相當簡單(雖然不是最優的效率):

String.prototype.repeat = function (n) { 
    if (n<1) return ''; 
    var accum = '', c=this; 
    for (; n; n >>=1) { 
     if (1&n) accum += c; 
     c += c; 
    } 
    return accum; 
}; 

function ngrammer(kgram, n) { 
    var m = n - kgram.length; 
    var branches = []; 
    for (var i = 0; i <= m; ++i) { 
     branches.push(('\\S'.repeat(i) + kgram + '\\S'.repeat(m-i) + '))').replace(/^\\?./, '$&(?=(')); 
    } 
    return new RegExp(branches.join('|'), 'ig'); 
} 

var onegram = ngrammer('A', 3); 
...