Pregunta

How can I optimise array search for value unset it and re-index searched array? It is ok, if i have small amount of data to search through, and small number of values compare to. But my application is fetching all web property links(2695) from Google Analytics API! Before displaying result into on screen i need to filter all links for removing blacklisted links(which will not be displayed on result page) from result array.

$b_links; //blacklisted links approximate amount 100-150
$google['analytics']; //all links from analytics except site search links  (~3000 links)
foreach ($b_links as $b_link){
    foreach ($google['analytics'] as $index=>$a_link){
            if ($b_link->uri===$a_link[0]){
                      unset($google['analytics'][$index]);
            }
     }
}

$google['analytics'] = array_values($google['analytics']);

I was getting-> Fatal error: Allowed memory size of 134217728 bytes exhausted after

ini_set('memory_limit', '-1');

i get-> Fatal error: Maximum execution time of 30 seconds Any ideas how i can re-factor code to use less memory and use less execution time. I was trying to send list of unwanted links as filter to Analytics api, but google limits request URI to 2000 chars! Thanks for your help!

How can i use array_filter? is it possible? will it be faster?

¿Fue útil?

Solución

Hmm following construction should be faster:

First of all reverse $b_links:

$b_links_reversed = array();
foreach($b_link => $b) {
    $b_links_reversed[$b->uri] = true;
}

Access to associative array should be faster. And now we can do it with one foreach:

foreach ($google['analytics'] as $index=>$a_link){
    if (isset($b_link_reversed[$a_link[0]])){
        unset($google['analytics'][$index]);
    }
}

Otros consejos

I'm going to propose three changes.

  1. Change foreach to normal for. This reduces the number of memory copies you make.
  2. Use array_splice instead of unset. This may be slightly slower than unset, but it will actually remove the value and the index from the array, reducing your memory footprint.
  3. Use a break statement to avoid extra looping on the inner loop after you find an item.

Sample code:

for($l = sizeof($links) - 1; $l >= 0; --$l) {
    for($a = sizeof($google['analytics']) - 1; $a >= 0; --$a) {
        if($b_links[$l]->uri === $$google['analytics'][$a]->$a_link) { //I think this check is slightly wrong, I'm not familiar with the => you use
            array_splice($links, $l, 1); //Remove the current element
            break;
        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top