10

consider the below script. two arrays with only three values.when i compare these two arrays using array_intersect(). the result is fast.

    <?php
$arrayOne = array('3', '4', '5');
$arrayTwo = array('4', '5', '6');

$intersect = array_intersect($arrayOne, $arrayTwo);

print_r($intersect );

?>

my question is what is the efficiency of the array_intersect(). whether if we compare two arrays both having 1000 values each. would produce better result..... r we need to use some hash function to deal with finding common values quickly which will be effective???.. i need ur suggestion for this...

i am doing an application.if an person comes and login using facebook login.then the application will get his friends list and find whether any friends as commented in my app before and show it to him. roughly a friends may have 200 to300 friends in facebook and db has more than 1000 records. i need to find that efficiently how can i do that.......

6
  • @learnfromothers : have you tried the same thing on arrays with 1000+ values? Commented Jun 13, 2011 at 10:33
  • 2
    why not find out yourself? do a benchmark. in general, it doesnt matter if its efficient or not unless you profiled your application and found that the calls to array_intersect are slowing down your application significantly. How much is significant is up to your requirements. Commented Jun 13, 2011 at 10:37
  • @Coding Freak no i have not tried that . i am doing an application.if an person comes and login using facebook login.then the application will get his friends list and find whether any friends as commented in my app before and show it to him. roughly a friends may have 200 to300 friends in facebook and db has more than 1000 records. i need to find that efficiently how can i do that....... Commented Jun 13, 2011 at 10:37
  • @Gordan for this any solution..... i am doing an application.if an person comes and login using facebook login.then the application will get his friends list and find whether any friends as commented in my app before and show it to him. roughly a friends may have 200 to300 friends in facebook and db has more than 1000 records. i need to find that efficiently how can i do that....... Commented Jun 13, 2011 at 10:38
  • But how can you be sure that you would come accross people who have only 200 to 300 friends? I have seen profiles on facebook that have more than 5K+ friends. Commented Jun 13, 2011 at 10:45

5 Answers 5

24

Intersection can be implemented by constructing a set of the searched values in the second array, and looking up in a set can be made so fast that it takes essentially constant time on average. Therefore, the runtime of the whole algorithm can be in O(n).

Alternatively, one can sort the second array (in O(n log n)). Since looking up in a sorted array has a runtime in O(log n), the whole algorithm should then have a runtime in O(n log n).

According to a (short, unscientific) test I just ran, this seems to be the case for php's array_intersect:

Performance of array_intersect

Here's the code I used to test it. As you can see, for an input size as small as 1000, you don't need to worry.

Sign up to request clarification or add additional context in comments.

6 Comments

@phinag ya thats right.... for this any solution..... i am doing an application.if an person comes and login using facebook login.then the application will get his friends list and find whether any friends as commented in my app before and show it to him. roughly a friends may have 200 to300 friends in facebook and db has more than 1000 records. i need to find that efficiently how can i do that.
@learnfromothers array_intersect will not be the performance problem for less than a thousand elements.
thanks. for your effect. very much statisfied with your answer.... thanks again.........
@phihag If you could remember, what was the tool you used to get that graph?
@vicch I apologize, I don't remember, and I can't find that code to generate the graph (the code to get the data, on the other hand, is linked to in the answer). This was probably gnuplot or matplotlib. But I cannot exclude LibreOffice or even a hand-coded script.
|
18

array_intersect sorts the arrays before comparing their values in parallel (see the use of zend_qsort in the source file array.c). This alone takes O(n·log n) for each array. Then the actual intersection does only take linear time.

Depending on the values in your arrays, you could implement this intersection in linear time without the sorting, for example:

$index = array_flip($arrayOne);
foreach ($arrayTwo as $value) {
    if (isset($index[$value])) unset($index[$value]);
}
foreach ($index as $value => $key) {
    unset($arrayOne[$key]);
}
var_dump($arrayOne);

Comments

5

The fastest solution I found:

function arrayIntersect($arrayOne, $arrayTwo) {
        $index = array_flip($arrayOne);
        $second = array_flip($arrayTwo);

        $x = array_intersect_key($index, $second);

        return array_flip($x);
}

Tests I have made looks like below:

function intersect($arrayOne, $arrayTwo)
{
    $index = array_flip($arrayOne);
    foreach ($arrayTwo as $value) {
        if (isset($index[$value])) unset($index[$value]);
    }
    foreach ($index as $value => $key) {
        unset($arrayOne[$key]);
    }

    return $arrayOne;
}

function intersect2($arrayOne, $arrayTwo)
{
    $index = array_flip($arrayOne);
    $second = array_flip($arrayTwo);

    $x = array_intersect_key($index, $second);

    return array_flip($x);

}

for($i =0; $i < 1000000; $i++) {
    $one[] = rand(0,1000000);
    $two[] = rand(0,100000);
    $two[] = rand(0,10000);
}

$one = array_unique($one);
$two = array_unique($two);

$time_start = microtime(true);
$res = intersect($one, $two);
$time = microtime(true) - $time_start;

echo "Sort time $time seconds 'intersect' \n";


$time_start = microtime(true);
$res2 = array_intersect($one, $two);
$time = microtime(true) - $time_start;

echo "Sort time $time seconds 'array_intersect' \n";


$time_start = microtime(true);
$res3 = intersect2($one, $two);
$time = microtime(true) - $time_start;

echo "Sort time $time seconds 'intersect2' \n";

Results from php 5.6 :

Sort time 0.77021193504333 seconds 'intersect' 
Sort time 6.9765028953552 seconds 'array_intersect' 
Sort time 0.4631941318512 seconds 'intersect2'

1 Comment

From Review: Hi, please don't answer just with source code. Try to provide a nice description about how your solution works. See: How do I write a good answer?. Thanks
2

From what you state above, I would recommend you to implement a caching mechanism. That way you would of load the DB and speed up your application. I would also recommend you to profile the speed of array_intersect with increasing amount of data to see how performance scale. You could do this by simply wrapping the call in calls for the system time and calculate the difference. But I would recommend you to use a real profiler to get good data.

6 Comments

@learnfromothers: A profiler is an application that helps you meassure the performance of your application. Look at Xdebug for example: xdebug.org/docs/profiler or if you use Zend Studio they have a built in one: files.zend.com/help/Beta/Zend_Studio_8_0/…
@inquam ya thanks. can i use some hash function to store the values in db so that the searching can be limited a bit. is that a right approach???
@learnfromothers: The best way to access your data is determined by a multitude of factors. The layout of the data, how frequent read and writes are etc. But with a profiler in place you can quickly see how different approaches and specific changes affect your performance.
@inquam thanks again.... but do u know any best methods used for efficient storage and retrieval of data in current days and in major website like facebook etc....
@laernfromothers: I know that Facebook for example relies heavily on caching of data. I think they use a modified version of memcache. This stores data in memory and is very fast, compared to getting the data from DB all the time. Also, I think that they pre-calculate key bits of information so that you don't have to do that each and every time. Say your friends list. You could compile that once and store it in cache memory. Then you could retrieve it from there each time you need it. Only once you add or remove a friend would it have to be rebuilt.
|
1

I implementing this simple code of comparing array_intersect and array_intersect_key,

$array = array();
    for( $i=0; $i<130000; $i++)
        $array[$i] = $i;
    for( $i=200000; $i<230000; $i++)
        $array[$i] = $i;
    for( $i=300000; $i<340000; $i++)
        $array[$i] = $i;

    $array2 = array();
    for( $i=100000; $i<110000; $i++)
        $array2[$i] = $i;
    for( $i=90000; $i<100000; $i++)
        $array2[$i] = $i;
    for( $i=110000; $i<290000; $i++)
        $array2[$i] = $i;

    echo 'Intersect to arrays -> array1[' . count($array) . '] : array2[' . count($array2) . '] ' . '<br>';
    echo date('Y-m-d H:i:s') . '<br>';
    $time = time();
    $array_r2 = array_intersect_key($array,$array2);
    echo 'Intercept key: ' . (time()-$time) . ' segs<br>';
    $time = time();
    $array_r = array_intersect($array,$array2);
    echo 'Intercept: ' . (time()-$time) . ' segs<br>';

the result....

Intersect to arrays -> array1[200000] : array2[200000] 
2014-10-30 08:52:52
Intercept key: 0 segs
Intercept: 4 segs

In this comparing of the efficency between array_intersect and array_intersect_key, we can see the interception with keys it is much faster.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.