আগামী ১৫ ডিসেম্বর -২০১৭ তারিখ থেকে শুরু হচ্ছে পাঁচ মাস ব্যাপী Professional Web Design and Development with HTML, CSS PHP,MySQL,JavaScript, AJAX, JQUERY, Bootstrap and Live Project কোর্সের ৮৭ তম ব্যাচ এবং ২৬ ডিসেম্বর-২০১৭ তারিখ থেকে শুরু হচ্ছে চার মাস ব্যাপী Zend PHP-7 Certified PHP Engineering (Advance PHP) কোর্সের ৩৫ তম ব্যাচ। প্রত্যেকটি কোর্স এর ফী নির্ধারণ করা হয়েছে ৩০,০০০/= আগ্রহীদেরকে অতিসত্বর মাসুদ আলম স্যার এর সাথে যোগাযোগ করতে অনুরোধ করা যাচ্ছে। স্যার এর মোবাইল: 01722 81 75 91

PHP’s in_array() function is really slow

isset() vs in_array()

PHP’s built in in_array() function that checks the existence of an element in an array is morbidly slow. If you’re looking up a lot of things in an array in rapid successions, I think theres a better way to do it. (provided that you aren’t checking for existence of arrays or objects)

Scenario

Imagine you need to know if various fruits is in your array of fruits, so first lets get an array of fruits.

$fruits = [
    "apple",
    "mango",
    "jackfruit",
    "strawberry",
    "dorian",
    "lichi",
    "tomato", //yes, tomato is a fruit.
    "fig",
    "custard-apple",
    "wax-apple",
    "pomegranate",
    "snake-fruit",
    "dragon-fruit"
];

So according to the PHP Docs you would check if the fruit “tomato” exists in your array with the in_array() function.

like so …

if (in_array("tomato", $fruits) {
    echo "Yes Tomato.";
} else {
    echo "No Tomato.";
}

but this is slow.

Is there a faster way?

Yes there is.

Use the isset() function! lets dive into the code…

$flipped_fruits = array_flip($fruits);

if (isSet($flipped_fruits["tomato"])) {
    echo "Yes Tomato.";
} else {
    echo "No Tomato.";
}

We flip the array with the array_flip() function so the values become the keys and the keys become the values. Then we test the existence of tomato with the isset() function checking the existence of the key “tomato”.

This is faster, and I have the benchmarks (or something like that) to prove it!

The Benchmark(-ish)

The benchmark is ultra simple. We’re using the microtime() function here. We could’ve used more advanced benchmark utilities, but this method is more than enough to prove the point.

The following code tests the speed of both methods. (the ‘echo’s were dropped, we don’t want it hogging up our output)

<?php
$fruits = [
    "apple",
    "mango",
    "jackfruit",
    "strawberry",
    "dorian",
    "lichi",
    "tomato", //yes, tomato is a fruit.
    "fig",
    "custard-apple",
    "wax-apple",
    "pomegranate",
    "snake-fruit",
    "dragon-fruit"
];

$cycles = 10**6; //one million


// -------------------------------
// ---------- in_array() ---------
// -------------------------------
$t1 = microtime(true);

for($i=0; $i < $cycles; $i++) {
    if (in_array("tomato", $fruits)) {
        "Yes Tomato.";
    } else {
        "No Tomato.";
    }
}

$t_a = microtime(true) - $t1;


// -------------------------------
// ----------- isset() -----------
// -------------------------------
$t2 = microtime(true);

$flipped_fruits = array_flip($fruits);

for($i=0; $i < $cycles; $i++) {
    if (isset($flipped_fruits["tomato"])) {
        "Yes Tomato.";
    } else {
        "No Tomato.";
    }
}

$t_b = microtime(true) - $t2;

// -------------------------------
// ---------- Conclusions --------
// -------------------------------
echo "in_array(): $t_a seconds. \n";
echo "isset():    $t_b seconds. \n";
echo "--------------------------\n";
echo "Factor: ".round($t_a/$t_b)."x";

So I ran it on my home PC running PHP 5.6 on Ubuntu 14.04, these were the output…

in_array(): 6.6512968540192 seconds. 
isset():    0.23910689353943 seconds. 
-------------------------- 
Factor: 28x

Yes! You read that correct! 28 times as fast! WOAH right?

What happens, when you check for an element that is not present like “potato”…

in_array(): 6.7724678516388 seconds. 
isset():    0.192626953125 seconds. 
-------------------------- 
Factor: 35x

Even Faster!

How?

Well, the first method uses the in_array() function, which behind the scenes goes through the whole array one element at a time and tries to match the values. So the time required is directly proportional to the position of the element and the size of the array.

On the other hand, when we search for them with keys, it does not need to go through every element, as keys are hashed.

You could imagine the keys being numeric and sorted behind the scenes. Every key has a unique numeric value and every time we give the same key the same numeric value is produced, which can be then used to jump to it’s location almost instantly!

The Catch!

Well, it works really fast, thats nice. But you cannot test for existence of objects and array using this method. Quite simply because PHP does not like the idea of objects and arrays being keys.

Thats not to say it can’t be done, maybe if the Objects have a __toString() method that returns unique strings those could be used to build the hashes, but that is another topic.

Also it requires a little more memory as now you have a hashtable along with the original array.

Hi, I am Omran Jamal from Bangladesh, a Student of A-Level, and an Intern at Techbeeo. Though young, I am very enthusiastic about Computers. Taught myself how to code when I was 12 and been coding ever since.

4 comments on “PHP’s in_array() function is really slow
  1. You called array_flip() just 1 time and in_array() every time but what will be the result if you call array_flip() every time ??
    First make compare between array_flip() vs in_array() then show your result

    • array_flip() and in_array() does not even do anything similar so logically it would make no sense to flip an array on every iteration. I might be wrong though, please let me know with code examples.

Leave a Reply

Your email address will not be published. Required fields are marked *