我正在寻找一个函数,它在一个较长的字符串('haystack')中找到一个字符串数组('needle')的子字符串。基本上我希望它像这个例子一样工作:
var haystack = "abcdefghijklmnopqrstuvwxyz";
var needles = [
'bcd',
'pqr',
'hi',
'ghi',
'g',
'stuv'
];
var output = findSubstring (haystack, needles, 2, 20);
输出现在应该有:
{index: 6, which: 3}
这意味着它在位置6处找到了“ghi”(针3)。它得到'ghi'而不是'hi',因为'ghi'在大海捞针中较早开始,但它没有得到'g',因为' ghi'在针阵列中较早。
这是我提出的最好的,但是对于非常大的文本块和非常大的针阵列(我正在使用它),它似乎相当慢,我相信有更好的东西。这是非常重要的性能因素,所以我真的更喜欢更快的东西。
我可以想象更好的方法(可能不使用indexOf),并且因为这(很可能)是一种非常常见的事情,那些对这类事情有更多经验的人可能有更好的方法去关于它。 (即我宁愿不重新发明轮子)
function findSubstring (haystack, needles, startIndex, endIndex) {
var min = Infinity, best = -1;
var numNeedles = needles.length;
if (!startIndex)
startIndex = 0;
for (var i=0; i<numNeedles; i++) {
var index = haystack.indexOf(needles[i], startIndex);
if (index != -1 && index < min) {
min = index;
best = i;
}
}
return (best == -1 || (endIndex && best >= endIndex)) ?
null :
{index: min, which: best};
}
答案 0 :(得分:3)
建议将你的针头组合成一个正则表达式:“bcd | pqr | hi | ghi | g | stuv”。
正则表达式引擎将这些组合成一个有效的有限状态机。
答案 1 :(得分:1)
http://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm将找到它们出现的所有字符串。成本是要搜索的字符串的大小加上找到的每个匹配的常量,加上与要查找的字符串集大小成线性的设置时间。你需要添加额外的逻辑来丢弃你似乎不想要的匹配。
答案 2 :(得分:0)
通过第一个字符将子字符串排序为单独的数组...一个以'a'开头的单词数组,另一个用于'b'的数组,依此类推。
将您的字符串转换为数组。
通过数组解析,一次一个字符,检查每个相关的子串数组以进行匹配。如果可以提高性能,请使用二进制搜索来加速检查子串数组。
答案 3 :(得分:0)
不是为你要去的每个字符串反复调用indexOf
,而是创建一个整数数组,在其中为每个字符串存储一次调用indexOf
的结果。
之后,您只需找到数组中的最小数字(不是-1),这是字符串中的第一个匹配项。然后,您只需更新数组中小于匹配后字符的项(而不是-1)。重复直到到达字符串的末尾,或者数组中的所有项都是-1。
答案 4 :(得分:0)
如果heyStack将是一个非常大的文本,那么每次发现一个针时切断其余的heyStack“可能”更好:
if (index != -1 && index < min) {
min = index;
best = i;
hayStack = hayStack.substring(0, index + indles[i].length);
}
答案 5 :(得分:0)
看看Knuth-Morris-Pratt算法,它可能对您的问题有用