6

ネストされた JSON オブジェクト内の文字列を検索したい。文字列がオブジェクトで見つかった場合は、そのオブジェクトを返す必要があります。

これを実現するために再帰関数を使用しています。問題は、関数が最後まで再帰的であり、見つかったオブジェクトを返さないことです。

jsfiddle のコード全体を参照してください

function search(obj, name) {
    console.log(obj["name"], ",", name, obj["name"] == name);

    if (obj["name"] == name) {
        return obj; //NOT RETURNING HERE
    } 
    if (obj.children || obj._children) {
        var ch = obj.children || obj._children;
        //console.log(ch);
        ch.forEach(function(val) {
            search(val, name)
        });
    }
    return -1;
}

search(myJson, "VM10-Proc4")

何が問題なのかわかりません。

4

5 に答える 5

8

一致する子が見つかったら、子のループを停止する必要があります。

function search(obj, name) {

    console.log(obj.name, ",", name, obj.name == name);

    if (obj.name == name) {
        return obj;
    }
    if (obj.children || obj._children) {
        var ch = obj.children || obj._children;
        for (var i = 0; i < ch.length; i++) {
            var found = search(ch[i], name);
            if (found) {
                return found;
            }
        }
    }
    return false;
}

フィドルのデモ

于 2013-03-28T05:15:46.803 に答える
5

再帰関数呼び出しのチェーンで正しい戻り値が失われています。正しい値が見つかった後、さらに検索を行うと、その時点から正しくない値が返されます。

これを処理するいくつかの方法:

1. 検索をキャンセルする

正しい値が見つかったら、現在の配列またはネストされた配列をこれ以上検索せずに、すぐに再帰スタックをすべて返します。つまり、残りの検索をキャンセルします。

@Barmerの答えはこの例です。彼のコードの重要な部分は、ループを中断する方がはるかに簡単であるため、配列を反復処理する方法forではなく、ループを使用することです。eachfor

2. 値を安全な場所に保存する

正しい値が見つかったら、それを安全な場所に保存し、残りの検索を続行して、最初の関数呼び出しが終了した後に値にアクセスします。最も簡単な方法は、正しい値をグローバル変数に格納することですが、関数のカプセル化に違反するため、良い方法ではありません。

@shyamの答えは、よりクリーンな解決策を示しています。グローバル変数への参照を関数パラメーターとして渡し、正しい値が見つかったときにパラメーターを設定し、最初の関数呼び出しが終了した後にグローバル変数にアクセスします。

2つの中から選択

素人の言葉で言えば、関数の意図したロジックは次のように要約できます。検索を続行する唯一の理由は、複数のデータを見つける必要がある場合です。ここではそうではないと思います。

2 つのアプローチのうち、#2 は問題なく動作するはずの応急処置の回避策ですが、関数の意図したロジックを理解しようとしている人をさらに混乱させるでしょう。既に見つかった 1 つのデータのみを探しているのに、なぜ検索が続くのでしょうか?

#1 は関数をリファクタリングして、意図したロジックとより一貫して動作するようにすることです。これにより、関数が理解しやすくなります。必要なものが見つかると、関数は検索を停止します。

于 2013-03-28T05:14:57.100 に答える
1

再帰を行っているため、意味のある結果を得るには、戻り値のネストが深すぎる可能性があります。代わりに、追加の引数を渡して結果を収集することができます。

function search(obj, name, ret) {
  console.log(obj["name"], ",", name, obj["name"] == name);

  if (obj["name"] == name) {
    ret.push(obj);
    return
  }
  if (obj.children || obj._children) {
    var ch = obj.children || obj._children;
    ch.forEach(function(val) {
      search(val, name, ret);
    });
  }
}

var result = [];
search(myJson, "VM10-Proc4", result)
于 2013-03-28T05:19:02.977 に答える