通过通配符字符串快速搜索数组

Fast array search by wildchar string?

本文关键字:搜索 数组 字符串 通配符      更新时间:2023-09-26

我有一个JavaScript数组,索引像net.up, net.down, net, err, err.warn

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

的净。*'将返回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>"); }

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

一种可能的优化方法—如果性能出于某种原因是非常关键的—可能是避免使用split分配数组,而是使用indexOf(找到下一个点)和substring逐位遍历每个字符串。但是那样的代码会复杂得多,而且可能不会更快,如果有的话。

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

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

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

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

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

的比较

一个可能的性能改进是使用switch而不是if..else语句,可能还有其他的。

它没有使用任何ECMA5代码,但确实需要ECMA3兼容性,所以它应该是相当浏览器友好的