我想用字典将字符串拆分成一系列单词。
以下功能只给我带字母边界的单词。
function spltToWord(prm){
var spltedAr = prm.split(/(?=[A-Z][a-z])/);
return spltedAr.join(" ").trim();
}
我想将文本分成字典/非字典单词。
例如:
Iamno123prisoner - 我不是123囚犯
USAisveryrich - 美国非常富有
Albertgaveme5rupees - Albert给了我5卢比
可以找到示例字典Here以供参考。
答案 0 :(得分:3)
如果字典包含很多单词,那么您需要一个更快的解决方案,而不是一次匹配一个单词与输入文本的子字符串。如果字典中有一万个单词,你必须用这种天真的方法做至少一万个字符比较。
更有效的解决方案是使用trie来存储字典单词。检查单词是否在字典中只需要通过字符串一次。
另一个优点是您可以从文本中的给定位置开始搜索最长匹配。以下代码段演示了此方法,其中包含一个足以处理示例的小字典。在本地运行代码时,可以用自己的字典替换它。
var Global = {
dictionary: [
'aa', 'I', 'i', 's',
'aah', 'am',
'aahed', 'no',
'aahing', '123',
'aahs', 'prisoner',
'aal', 'USA',
'aalii', 'is',
'aaliis', 'very',
'aals', 'rich',
'aardvark', 'Albert',
'aardvarks', 'gave', 'me', '5', 'rupees'
]
};
function addToTrie(word) {
var node = Global.trie;
for (var pos = 0; pos < word.length; ++pos) {
var letter = word.charAt(pos);
if (node[letter] === undefined) {
node[letter] = {};
}
node = node[letter];
}
node.terminal = true;
}
function findLongestMatch(text, start) {
var node = Global.trie,
best = start - 1;
for (var pos = start; pos < text.length; ++pos) {
var letter = text.charAt(pos);
if (node[letter] === undefined) {
break;
}
node = node[letter];
if (node.terminal) {
best = pos;
}
}
return best - start + 1;
}
function loadTrie() {
var words = Global.dictionary,
trie = Global.trie = {};
words.forEach(function (word) {
addToTrie(word);
});
};
function println(label, s, labelStyle) {
if (s === undefined) {
s = label || '';
} else {
var className = 'label' + (labelStyle ? ' ' + labelStyle : '');
s = '<div class="' + className + '">' + label + '</div> ' + s;
}
document.getElementById('message').innerHTML += (s + '<br />');
}
function process(text) {
var results = [],
letters = [],
pos = 0;
while (pos < text.length) {
var length = findLongestMatch(text, pos);
if (length == 0) {
letters.push(text.charAt(pos));
pos += 1;
} else {
if (letters.length != 0) {
results.push({ word: letters.join(''), known: false });
letters = [];
}
results.push({ word: text.substring(pos, pos + length), known: true });
pos += length;
}
}
if (letters.length != 0) {
results.push({ word: letters.join(''), known: false });
letters = [];
}
var breakdown = results.map(function (result) {
return result.word;
});
println();
println(' breakdown:', '/' + breakdown.join('/') + '/');
results.forEach(function (result) {
println((result.known ? 'in dictionary' : ' unknown') + ':',
'"' + result.word + '"', (result.known ? undefined : 'unknown'));
});
};
window.onload = function () {
loadTrie();
process('WellIamno123prisoner');
process('TheUSAisveryrichman');
process('Albertgaveme5rupeesyo');
};
body {
font-family: monospace;
color: #444;
font-size: 14px;
line-height: 20px;
}
.label {
display: inline-block;
width: 200px;
font-size: 13px;
color: #aaa;
text-align: right;
}
.label.unknown {
color: #c61c39;
}
<div id="message"></div>
答案 1 :(得分:1)
编辑#2
var words = ["apple", "banana", "candy", "cookie", "doughnut"];
var input = "banana123candynotawordcookieblahdoughnut";
var currentWord = "",
result = "";
while (true) {
for (var i = 0; i < input.length; i++) {
currentWord += input[i];
if (words.indexOf(currentWord) >= 0) {
result += " " + currentWord + " ";
currentWord = "";
}
}
if (currentWord.length > 0) {
result += currentWord[0];
input = currentWord.substr(1);
currentWord = "";
} else {
break;
}
}
console.log(result.trim()); // "banana 123 candy notaword cookie blah doughnut"
注意如果有两个连续的字典单词,结果将包含两个空格。您可以使用正则表达式修复此问题。
它不是最漂亮的解决方案(你可以使其递归,可能更具可读性),并且它不提供多种解决方案(请参阅评论中的DP链接)。
编辑这并未考虑非词典单词。
使用简单的贪婪算法:
var words = ["apple", "banana", "candy", "cookie", "doughnut"];
var input = "bananacandycookiedoughnut";
var currentWord = "", result = "";
for (var i = 0; i < input.length; i++) {
currentWord += input[i];
if (words.indexOf(currentWord) >= 0) {
result += currentWord + " ";
currentWord = "";
}
}
console.log(result.trim()); // "banana candy cookie donught"
当然你想修改其中的各个部分,例如使用字典集并考虑案例[in]敏感度。