2016-12-25 9 views
0

私はこのようになりますJSONを解析する必要があります。PHP再帰JSON子供検索

{ 
    "mdfId":"282088127", 
    "mdfConcept":"ME 3400EG-12CS-M Switch", 
    "children":[ 
     { 
      "mdfId":"007", 
      "mdfConcept":"Another item", 
      "children": [ 
       // many more here 
      ] 
     }, 
     { 
      "mdfId":"008", 
      "mdfConcept":"Another one", 
      "children": [ 
       { 
        "mdfId":"010", 
        "mdfConcept":"What I'm looking for!", 
        "children": [] // no children 
       } 
      ] 
     }, 
     // many more here 
    ] 
}, 

これは、すべての要素がmdfIdmdfConceptchildrenキーを持っている再帰構造です。

私はこの構造内にノードID=010を見つける必要があります。どのレベルにあるのかはわかりません(たとえば、トップレベルにある場合もあれば、複数のノードがある場合はchildren)。

私の現在のアプローチは、次のとおりです。

$mdfId = '010'; // what I'm loking for 

foreach ($jsonResponse as $category) { 
    while (true) { 
     if ($category['mdfId'] == $mdfId) { 
      // we found it! 
      $categoryDevices[$mdfId] = $category['children']; 
      break 2; 
     } 

     if (!empty($category['children'])) { 
      next_cat: 

      if (is_null($category['children'])) { 
       break; 
      } 

      $category = array_shift($category['children']); 
      continue; 
     } 

     if (empty($category['children'])) { 
      goto next_cat; 
     } 
    } 
} 

しかし、現在のアプローチは、いくつかの例をミス。この再帰ループを最適化して、同じレベルのすべてのノードと、任意の数のchildrenキーを介してアクセス可能なノードをすべてチェックするにはどうすればよいですか?

答えて

0

だから、基本的に何も返さない関数を書いたのですが、むしろ引数から変数を移入しました。

function findRecursiveArrayNodeById($id, $array, &$node) { 
    foreach ($array as $child) { 
     if (isset($child['mdfId']) && $child['mdfId'] == $id) { 
      $node = $child; 
      return; 
     } 

     if (!empty($child['children'])) { 
      findRecursiveArrayNodeById($id, $child['children'], $node); 
     } 
    } 
} 

使用法を次のように

$result = false; 

findRecursiveArrayNodeById($mdfId, $category_json, $result); 

if (!$result) { 
    println("did not find {$mdfId}"); 
    continue; 
} 
1

あなたのJSONオブジェクトの恥ずかしいな特徴は、各childrenメンバーが「子」構造体の配列である一方で、トップレベル1は、オブジェクト自体あるので、それは本当に再帰アプローチへの障害だ、ということです。

我々はすなわち、ネストされたレベルと同じ構造にソースJSONオブジェクトを回転させることによって回避可能性があります$jsonResponse

  • 元のオブジェクトとして使用 ['children' => $jsonResponse]代わり

    この方法を持つ

    • 、それは

      $mdfId = '010'; // what I'm loking for 
      
      if ($result = look4id(['children' => $jsonResponse], $mdfId) { 
          $categoryDevices[$mdfId] = $result; 
      } 
      
      function look4id($source, $id) { 
          foreach ($source as $child) { 
           if ($child['mdfId'] == $id) { 
            return $source['children']; 
           } else { 
            if ($source['children']) { 
             return look4id($source['children'], $id); 
            } 
           } 
          } 
      } 
      
    +0

    全体的に良い答えとアプローチ。所見率を30%から60%に高めることができました。しかし、いったんループがいくつかの '子どもたち 'に深く入り込むと、より高いレベルの手つかずの要素について忘れてしまいます。したがって、「007」と「008」が逆順に配置された場合、スクリプトは「008」とその子「010」をチェックし、「007」は完全に逃してしまいます。 –

    +0

    @DenisBobrovnikov Hum ...面白い問題!あまり重すぎない場合は、JSONオブジェクトの例を投稿しても、見つからないキーはありますか? (OPを編集してオブジェクトをSOのスニペットに入れることができます) – cFreed

    関連する問題