2017-01-05 4 views
3

私はこれを一日中研究しており、解決策を見いだせませんでした。私はまた、PHPには非常に新しいです。PHP foreachループは不要な配列を返す(Wikipedia API)

私の機能の目的は、Wikipediaの記事のユーザー入力(Category1)を取り、そのカテゴリを返すことです。以下の基本的な機能は問題なくこれを行います。

function get_all_categories () { 

     $url = $this->get_url ('categories') ; 
     $url .= 'titles='.urlencode($_POST['Category1']); 
     $url .= '&cllimit=500' ;   
     $data = $this->get_result ($url) ; 

     $array = json_decode($data, true); } 

都市計画のためになる:

Array 
(
[batchcomplete] => 
[query] => Array 
    (
     [pages] => Array 
      (
       [46212943] => Array 
        (
         [pageid] => 46212943 
         [ns] => 0 
         [title] => Urban planning 
         [categories] => Array 
          (
           [0] => Array 
            (
             [ns] => 14 
             [title] => Category:All Wikipedia articles written in American English 
            ) 

           [1] => Array 
            (
             [ns] => 14 
             [title] => Category:Commons category with local link same as on Wikidata 
            ) 

           [2] => Array 
            (
             [ns] => 14 
             [title] => Category:Pages using ISBN magic links 
            ) 

           [3] => Array 
            (
             [ns] => 14 
             [title] => Category:Urban planning 
            ) 

           [4] => Array 
            (
             [ns] => 14 
             [title] => Category:Use American English from April 2015 
            ) 

           [5] => Array 
            (
             [ns] => 14 
             [title] => Category:Use dmy dates from April 2015 
            ) 

           [6] => Array 
            (
             [ns] => 14 
             [title] => Category:Wikipedia articles needing clarification from June 2015 
            ) 

           [7] => Array 
            (
             [ns] => 14 
             [title] => Category:Wikipedia articles with GND identifiers 
            ) 

          ) 

        ) 

      ) 

    ) 

) 

私はこの配列からタイトルのみ値を抽出しようとすると、私の問題が開始されます。私は、多次元配列見つかり最も簡単な解決策であるforeachループでこれを行うことを試みてきました:

$array1 = new RecursiveIteratorIterator(
     new RecursiveArrayIterator($array), 
     RecursiveIteratorIterator::SELF_FIRST); 

     foreach ($array1 as $key => $value) { 
      if (is_array($value) && $key == 'categories') { 
       $result = array_map(function($element){return $element['title'];}, $value); 

       print_r($result); 
       }    
     } 

は、私はこのコードを取得すると、2つの配列です。タイトルのみ(私が欲しかったもの)が、また、不要な配列(いつか最初のタイトルが含まれます)の端部に取り付けられ伴う一つの配列:

Array 
(
[0] => Category:All Wikipedia articles written in American English 
[1] => Category:Commons category with local link same as on Wikidata 
[2] => Category:Pages using ISBN magic links 
[3] => Category:Urban planning 
[4] => Category:Use American English from April 2015 
[5] => Category:Use dmy dates from April 2015 
[6] => Category:Wikipedia articles needing clarification from June 2015 
[7] => Category:Wikipedia articles with GND identifiers 
) 
Array 
(
[ns] => 
[title] => C 
) 

は、この余分な配列が、私は理解していないものです。私は問題がforeachループによって引き起こされると思います。私はループの外で$変数を設定しないようにしましたが、それは助けになりませんでした。これらの結果を別の関数に渡そうとすると、特別な配列が特に面倒になります。これを防ぐ方法を教えてください。

答えて

1

簡略化のため、RecursiveIteratorIteratorではなく、手動で配列をトラバースすることができます。

RecursiveIteratorIteratorkill performance大型アレイの場合。

これにあなたの抽出ロジックを変更します。@samirが言及したよう

$result = array(); 
foreach($arr['batchcomplete']['query']['pages'] as $k => $v) 
{ 
    foreach($v['categories'] as $cat) 
    { 
     $result[] = $cat['title']; 
    } 
} 

Working Demo

+1

完全に動作します。ありがとうございました! – Sabaghian

1

が、それは手動でそれを行うには速いだろうが、あなたは、検索メカニズムが必要な場合には、未知の深さを横断基本的な再帰関数を使用することもできます。 PHPのmisfeaturesの面白い組み合わせだ

function recurse($array,&$new) 
    { 
     foreach($array as $key => $value) { 
      if($key == 'title' && isset($array['ns'])) { 
       if(!isset($array['pageid'])) 
        $new[] = $value; 
      } 
      else { 
       if(is_array($value)) { 
        recurse($value,$new); 
       } 
      } 
     } 
    } 

# Set's storage array for final titles 
$new = array(); 
# Recurse your array 
recurse($array,$new); 
# Show stored values 
print_r($new); 
0

:それはOOPスタイルのRecursiveArrayIterator/RecursiveIteratorIteratorより少し速いかもしれません

  • $key == 'categories'は、非タイプセーフな比較であるが、数値配列キーは整数であり、整数と文字列を比較するために、PHPはその文字列を整数にキャストします。おおまかに言えば、数値からなる文字列の最長の接頭辞を取ります。文字列が数字で始まっていない場合、文字列から整数への変換の結果は0です。
    categoriesサブアレイと最初の子(キーが0のもの)の場合、条件は2回trueになります。ヒント:比較のために常に===を使用してください。
  • PHPでは、配列ではないもの(ほとんどの場合nullを返す)のほとんどで[](配列インデックス)演算子を使用できます。したがって、array_map$element = 14(サブアレイの最初の子のアイテム)に対して$element['title']を取得しようとすると、成功し、nullになります(var_dumpは空白として表示されます)。
  • 文字列は少し異なります。'foo'[$n]は、文字列の$n番目の文字を取得するための有効な従来の構文です。配列インデックス演算子が整数でないインデックスを持つ文字列で使用されている場合、インデックスは整数にキャストされます(通常、結果はゼロになります)。したがって'Category:...'['title']は、文字列'C'になります。
    構造体が不明または信頼できない配列に対して配列インデックス構文を使用する場合は、常に信頼できないものとし、issetまたは同様のものを使用して、取得しようとしている配列フィールドが存在することを確認してください。
関連する問題