1

FacebookPHPSDKによって返される大きな配列を移動するのに助けが必要です。ユーザーからのすべての投稿を検索しようとしています。次に、投稿に「リンク」キーが含まれているかどうかも確認します。1MB以上のデータをコピーして処理するため、このサイズの配列でforeachループを使用するのは非効率的であると読みました。情報を効果的にトラバースするにはどうすればよいですか?

配列は次のように構成されています。ここで、「x」は各投稿の番号です。

Array
(
    [data] => Array
        (
            [x] => Array
                (
                    [from] => Array
                        (
                            [name] => james
                        )

                    [message] => Thanks for the great interview! 
                    [link] => http://example.com/link.html
                    [description] => Description here
                    [etc] => Various other keys possible
                )
        )
)

次に、私の現在のコードは次のようになります。ここで、$feedはFacebookAPIからの配列です。

for ($x=0, $y=0; $x<=1000, $y<=19; $x++) {

    if (array_key_exists('james', $feed['data'][$x]['from']['name'])) {

        if (!array_key_exists('link', $feed['data'][$x])) {

            echo "<div>" . $feed['data'][$x]['message'] . "<hr>" . $feed['data'][$x]['description'] . "</div>";

            $y++;
        };

    };

};

さまざまなイテレータについて読んだことがありますが、どれを使用すればよいかわかりません。あなたが私を助けてくれることを願っています、乾杯、ジョー

4

3 に答える 3

1

foreachのパフォーマンスについて話し、実際にarray_key_existsを使用することは、ナンセンスです。

foreach($feed['data'] as $post){
           if($post['from']['name']==='youruser'){
            //has user
           }
          if(isset($post['link'])){
            //has link
          }
}     

それをcillosisの方法で置くと、より速くなるはずです。

于 2012-04-29T12:20:20.907 に答える
1

foreachデフォルトでは値のコピーを使用し、前述のように、コピーはメモリを消費し、少し時間がかかる可能性があるため、大きな配列を反復処理すると遅くなる可能性があるという事実は正しいです。

ただし、 foreach を使用する別の方法は、コピーを作成しない参照によるものです。元の値で動作します。これは、配列のサイズに関係なく、再びメモリに配置されないことを意味します。別の StackOverflow ユーザーによって共有される参照による foreachの例を次に示します。

$a = array('hello', 'world');
$asRef =& $a;
$ontime = 0;
foreach($asRef as $i => $v)
{
   if (!$ontime++) $a = array('hash', 'the cat');
   echo " $i: $v\n";
}

C で記述された非常に高速な SPL からArrayIteratorを使用するオプションがあります。それがどのように機能するかの簡単な例:

// This would be your large facebook array
$big_array = array(1,2,3,...,10000,10001);

// Get the iterator object
$array_iterator = new ArrayIterator($big_array);

foreach($array_iterator as $item)
{
   //Do something with $item here
}

私はベンチマークを行っていませんが、参照によって配列を渡し、ArrayIterator を使用することがおそらく良い解決策になると思います。

于 2012-04-29T12:01:02.573 に答える
-1

foreachは常にコピーするとは限りません。コピーするときは、繰り返される直接のデータ構造のみをコピーします。値はコピーされません。たとえば、あなたがした場合

foreach ($arr['data'] as $k => $v) ....

100個のサブ要素([x]と省略)がある場合、配列を作成し、それらの100個のキーをコピーしますが、キーが指す値(値はサブ配列/ツリー)をコピーしません。内部的には、ポインタを格納し、コピーせずにサブアレイのメモリアドレスを指すようにします。

実際にコピーされるデータの量はごくわずかなので、あなたは何の役にも立たないと思います。foreachはほとんどの場合非常に高速です...

垣間見る場合は、ループの前後でmemory_get_usage()とmemory_get_peak_usage ()を確認してください。

于 2012-04-29T14:47:35.220 に答える