3

本当はredisでnode.jsを好きになりたいのですが、非同期性を克服できません。繰り返しますが、従来のデータベースと言語での単純なタスクがあります。私の質問は、問題解決のアプローチが最適かどうかというよりも、非同期データベース フェッチで制御フローとロジックを達成することに関するものです。

これが私がやろうとしていることです:私は単語で構成されたredisキーを持っていcarますcard。ここで、入力文字列が与えられたときに、redis のキーに一致する最長の部分文字列を知りたいと思います。指定された文字列の位置 0 から始まる部分文字列のみをチェックする必要があるため、複雑さは低くなります。

例:cardinalにはキーが含まcardれていますcarが、cardより長くなります。Capeどちらのキーとも一致しません。

私のアプローチは次のとおりです。文字列全体から始めて、キーと一致するかどうかを確認します。もしそうなら、その鍵を返してください。それ以外の場合は、文字列から最後の文字を除いた同じプロセスを繰り返します。

どうすればこのタスクを達成できますか? さまざまなアプローチを歓迎します。

async私はライブラリについて少し知っていwaterfallますが、私がやっていることには最適のようです。ただし、string.length、string.length-1 などから最後の 1 文字まで、すべての関数を入力する必要があるようです。私が探しているのは、 for ループの代わりにブレークを使用するのに適したものです。

以下では、常に 3 文字以上であると想定する入力を使用してテストします (既に見苦しく、ネストを増やすことはテストには意味がないように思われるため)。それは動作し、carde結果としてcard, とcare-> car. ナンセンス を与え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);
          }
        }
      });
  }
}
4

1 に答える 1

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);
于 2012-05-02T03:24:52.333 に答える