通过wildchar字符串进行快速数组搜索?

时间:2013-06-17 22:14:33

标签: javascript

我在JavaScript中有一个数组,其索引类似于net.up, net.down, net, err, err.warn

我有一个字符串,我需要找到与字符串匹配的所有索引。匹配有一些特殊的规则,但是......

'net。*'将返回net.up, net.down
'err'只会返回err

这是非常严格的,即'net.u *'不会返回任何内容。

目前,我正在考虑按句点拆分字符串,并将每个细分与每个细分进行比较,但这似乎很幼稚。

根据要求,我的代码有效,但我觉得太天真,希望改进:

o = {"hey":0,"hey.a":1,"hey.b":1,"no":0};
srch = "hey.*".split(".");
for(i in o) {
  match = true;
  parts = i.split(".");
  for(j=0;j<srch.length;j++) {
    if (parts[j]=="*" || srch[j]=="*") continue;
    if (parts[j] != srch[j]) {
      match=false;
      break; } }
  if (match)
    document.write("match: "+i+"<br>"); }

3 个答案:

答案 0 :(得分:0)

我不认为按句点分割字符串是天真的。要确定匹配,您需要验证输入字符串的每个部分是否与模式的每个部分匹配。这似乎就是你想要做的。

一种可能的优化方法 - 如果性能出于某种原因超级关键 - 可能是为了避免使用split分配数组,而是用indexOf逐位遍历每个字符串(以查找下一个点)和substring。但是,如果有的话,那些代码将会更加复杂,而且可能几乎没有更快。

答案 1 :(得分:0)

在检查你的编辑后,这就是我的建议,在正则表达式的帮助下,你可以创建你想要的任何模式,不需要创建自己的通配符系统;正则表达式是最终的通配符:

var obj = {"hey":0,"hey.a":1,"hey.b":1,"no":0};

var hey = Object.keys(obj).filter(function(key){
  return /^hey\.?.*?$/.test(key);
});

console.log(hey); //=> ["hey", "hey.a", "hey.b"]

修改:如果你只想要一个通配符,你仍然可以使用正则表达式,如下所示:

function filterwild(obj, wild) {
  wild = new RegExp('^'+ wild.replace(/\.(.+?)\*/,'\\.$1.*?') +'$');
  return Object.keys(obj).filter(function(k){ return wild.test(k) });
}

console.log(filterwild(obj,'hey')); //=> ["hey"]
console.log(filterwild(obj,'hey.*')); //=> ["hey","hey.a","hey.b"]
console.log(filterwild(obj,'hey.a*')); //=> ["hey.a"]

wild为您提供了/^hey\.a.*?$/(最后一个例子)的正则表达式。不确定这是你需要的确切输出;您可以根据需要调整正则表达式。

以上是上述快速演示:http://jsbin.com/ahixeq/2/edit

答案 2 :(得分:0)

如果我已正确理解了问题和评论,那么也许你正在寻找类似的东西。

的javascript

var o = {
    "hey": 0,
    "hey.a": 1,
    "hey.b": 1,
    "no": 0
};

function filterWild(object, search) {
    var length = search.length,
        matches = [],
        searchLength = Infinity,
        length;

    if (length > 2 && search.slice(-2) === ".*") {
        search = search.split(".");
        length = search.length ;

        if (length > 2) {
            search = search.slice(-1).join(".") + ".";
            searchLength = search.length;
        } else if (length === 2) {
            search = search[0] + ".";
            searchLength = search.length;
        } else {
            search = search[0];
        }
    }

    for (i in o) {
        if (o.hasOwnProperty(i) && i.slice(0, searchLength) === search) {
            matches.push(i);
        }
    }

    return matches;
}

console.log(filterWild(o, "hey"));
console.log(filterWild(o, "hey.*"));
console.log(filterWild(o, "hey.a*"));

输出

["hey"]
["hey.a", "hey.b"]
[] 

jsfiddle

以上是jsperf上述函数与正则表达式版本

可能的性能提升是使用switch代替if..else语句,可能还有其他语句。

它没有使用任何ECMA5代码,但确实需要ECMA3兼容性,因此它应该对浏览器友好。