2012-05-01 29 views
3

我真的想用redis来支持node.js,但我无法克服异步性。再次,我在传统数据库和语言中有什么是简单的任务。我的问题更多的是关于完成异步数据库抓取中的控制流和逻辑,而不是我的问题解决方法是否最优。异步查找子字符串匹配。递归?扁平化?

下面是我想要做的:我有redis键由单词组成,我们只需说carcard。现在,给定一个输入字符串,我想知道最长的子字符串是什么,它匹配redis中的一个键。我只需要检查从给定字符串的位置0开始的子字符串,所以复杂度很低。

例如:cardinal其中密钥card,还有car,但card更长。 Cape与任何一个键都不匹配。

我的方法是:从整个字符串开始,检查它是否与键匹配。如果是,请返回该密钥。否则,用字符串减去最后一个字符重复相同的过程。

我该如何完成这项任务?欢迎使用不同的方法。

我对async库有一点了解,它看起来像waterfall最适合我在做的事情。但是,似乎我需要从string.length,string.length-1等键入所有的函数,直到最后一个单个字符。我正在寻找的是一个很好的替代for循环休息。

下面我测试一个输入,我认为它总是3个字符或更多(因为它已经很丑并且更多的嵌套对测试似乎没有意义)。它的工作原理是carde导致cardcarecar。废话给no match

var http = require("http"); 
var redis = require("redis"); 

http.createServer(function(request, response) { 
    client = redis.createClient(); 
    word = "carde"; 
    client.keys(word, function(err, reply) { 
     if(err) { response.end(err); client.end(); } 
     else { 
      if(reply.length > 0) { 
      response.end(word); 
      client.end(); 
      } 
      else { 
      client.keys(word.slice(0,-1), function(err, reply) { 
       if(err) { response.end(err); client.end(); } 
       else { 
        if(reply.length > 0) { 
        response.end(word.slice(0, -1)); 
        client.end(); 
        } 
        else { 
        client.keys(word.slice(0, -2), function(err,reply) { 
         if(err) { response.end(err); client.end(); } 
         else { 
          if(reply.length > 0) { 
          response.end(word.slice(0, -2)); 
          client.end(); 
          } 
          else { 
          response.end("no match"); 
          } 
         } 
         }); 
        } 
       } 
       }); 
      } 
     } 
    }); 
    }).listen(8000); 

我也试过递归,它可能是最好的方法。 (感谢Timonthy Strimple纠正错误)。

http.createServer(function(request, response) { 
    client = redis.createClient(); 
    recursiveKeys("cardinalsin", client, response); 
    }).listen(8000); 

function recursiveKeys(word, client, response) { 
    if (word.length == 0) { 
    response.write("0"); 
    response.end(); 
    client.end(); 
    } 
    else { 
    client.keys(word, function(err, reply) { 
     if(err) { 
      response.write("0"); 
      response.end(); 
      client.end(); 
     } 
     else { 
      if(reply.length > 0) { 
      response.write(word); 
      response.end(); 
      client.end(); 
      } 
      else { 
      return recursiveKeys(word.slice(0,-1), client, response); 
      } 
     } 
     }); 
    } 
} 
+0

搜索词语在你递归的例子,你是不是收发响应到递归函数调用。 'return recursiveKeys(word.slice(0,-1),client)' –

+0

@TimothyStrimple感谢您指出这一点。现在的递归工作:) –

回答

4

我同意递归解决方案可能是最好的。在研究你的代码之前(为了不影响实验)我碰到了这个问题,并且得出了一个非常类似的解决方案。与http://localhost:3000/?word=cardinal

var http = require('http'); 
var redis = require('redis'); 
var url = require('url'); 

var findWord = function(needle, client, callback) { 
    if (needle.length <= 0) { return callback("Word not found") } 

    client.keys(needle, function(err, reply) { 
    if (err) { callback("Word not found"); } 
    else { 
     if (reply.length > 0) { 
     callback(needle); 
     } else { 
     findWord(needle.slice(0, -1), client, callback); 
     } 
    } 
    }); 
}; 

var server = http.createServer(function(request, response) { 
    var query = url.parse(request.url, true).query; 
    var word = query.word || ""; 
    var client = redis.createClient(); 

    findWord(word, client, function(found) { 
    client.end(); 
    response.writeHead(200, {"Content-Type": "text/plain"}); 
    response.end(found); 
    }); 
}); 
server.listen(3000); 
+0

哇,这就是额外的一英里,谢谢:)到目前为止,节点就像一个伟大的拼图给我。有时候感觉它限制了我,但现实可能是我对程序模式感到太舒服了。我认为节点和我习惯的东西是一种混合体。 –

+0

让我想起Alan Alan Perlis的一句话:“一种不影响你对编程思维方式的语言,是不值得了解的。”我喜欢Node的其中一件事是,它会迫使你陷入一种你通常不习惯的思维方式,并帮助你练习异步思维。祝你好运! –