1
\$\begingroup\$

I have been trying to parse results and make sure when I am doing so that I don't repeat the same data. I tried to use a few different options built into php with no luck. I did find an example of a recursive array search that seems to work but it's very intensive and adds a lot of time to the script.

What I'm needing: Does anyone know a better way to handle this without changing the array that I supply to it so something built-in like in_array or array_search?

Array example:

array (size=3)
 0 => 
 array (size=3)
 'author' => string 'Jim Beam' (length=8)
 'id' => string '1' (length=1)
 'md5' => string 'f2ebf4d4f333c31ef1491a377edf2cc4' (length=32)
 1 => 
 array (size=3)
 'author' => string 'Jack Daniels' (length=12)
 'id' => string '2' (length=1)
 'md5' => string 'd1839707c130497bfd569c77f97ccac7' (length=32)
 2 => 
 array (size=3)
 'author' => string 'Jose Cuervo' (length=11)
 'id' => string '3' (length=1)
 'md5' => string '64e989b4330cc03dea7fdf6bfe10dda1' (length=32)

Code example:

function recursive_array_search($needle,$haystack) {
 foreach($haystack as $key=>$value) {
 $current_key=$key;
 if($needle===$value OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
 return $current_key;
 }
 }
 return false;
}
$agentArray = array(
 array('author'=>'Jim Beam','id'=>'1','md5'=>'f2ebf4d4f333c31ef1491a377edf2cc4'),
 array('author'=>'Jack Daniels','id'=>'2','md5'=>'d1839707c130497bfd569c77f97ccac7'),
 array('author'=>'Jose Cuervo','id'=>'3','md5'=>'64e989b4330cc03dea7fdf6bfe10dda1')
);
$fakeMD5 = '84d7dc19766c446f5e4084e8fce87f82'; //StackOverflow MD5
$realMD5 = 'd1839707c130497bfd569c77f97ccac7'; //Jack Daniels MD5
echo '<b>In_Array:</b> <br/>';
$faketest = in_array($fakeMD5,$agentArray);
$realtest = in_array($realMD5,$agentArray);
var_dump($faketest,$realtest);
echo '<b>Search_Array:</b> <br/>';
$faketest2 = array_search($fakeMD5,$agentArray);
$realtest2 = array_search($realMD5,$agentArray);
var_dump($faketest2,$realtest2);
echo '<b>Custom Recursive Array Seach Function:</b> <br/>';
$faketest3 = recursive_array_search($fakeMD5,$agentArray);
$realtest3 = recursive_array_search($realMD5,$agentArray);
var_dump($faketest3,$realtest3);

Results:

In_Array:
Fake: boolean false
Real: boolean false
Search_Array:
Fake: boolean false
Real: boolean false
Custom Recursive Array Seach Function:
Fake: boolean false
Real: int 1
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Aug 23, 2013 at 21:23
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Also for PHP 5.5+ there is a simpler option, array_search($value, array_column($array, $key)); see stackoverflow.com/a/24527099/207603 (there is also a link to a backport for < PHP 5.5) \$\endgroup\$ Commented Jan 22, 2015 at 9:38

2 Answers 2

1
\$\begingroup\$

I have two comments.

First, what is the purpose of $current_key? Since you're not changing it, just use $key.

Second, by your usage, I'd say that

foreach ($haystack as $key => $item)
 if ($item["md5"] === $needle) return $key;
return false;

is quite enough. Of course, if the above was just an example and you really want to check all the values in (sub)arrays, then the above is O.K.

Of course, be careful when using this function, because key 0 may be interpreted as false.

A bit neater (but essentially the same) function was provided on Stack Overflow here. I like the additional $strict argument there (which you may or may not need).

answered Aug 23, 2013 at 22:17
\$\endgroup\$
1
  • \$\begingroup\$ Yeah thats not my function someone added that in a different thread but I think I overlooked the simplicity of my operation. I will use your example and see if its faster! \$\endgroup\$ Commented Aug 23, 2013 at 22:25
1
\$\begingroup\$

I will echo what Radu posted as a comment. I find a combination of array_search() with array_column() to be concise and easy to read. While foreach loops can perform slightly faster, using purpose-built native php functions can improve comprehension based on their names. Lines of code are reduced as well, if that is important to you, because array_search() bundles the array iteration, condition statement, and the return/break tasks.

Code: (Demo)

$agentArray = array(
 array('author'=>'Jim Beam','id'=>'1','md5'=>'f2ebf4d4f333c31ef1491a377edf2cc4'),
 array('author'=>'Jack Daniels','id'=>'2','md5'=>'d1839707c130497bfd569c77f97ccac7'),
 array('author'=>'Jose Cuervo','id'=>'3','md5'=>'64e989b4330cc03dea7fdf6bfe10dda1')
);
$fakeMD5 = '84d7dc19766c446f5e4084e8fce87f82'; //StackOverflow MD5
$realMD5 = 'd1839707c130497bfd569c77f97ccac7'; //Jack Daniels MD5
echo 'StackOverflow MD5 result: ';
var_export(array_search($fakeMD5,array_column($agentArray,'md5'),true)); // returns false : not found
echo "\nJack Daniels MD5 result: ";
var_export(array_search($realMD5,array_column($agentArray,'md5'),true)); // returns 1 : offset of the subarray

Output:

StackOverflow MD5 result: false
Jack Daniels MD5 result: 1

Now some notes about "strict" / "indentical" searching and the search results:

  • I have included the third parameter true to the array_search() function. This is important if the needle ($xxxxMD5) comes from an untrustworthy source (e.g. user input). The reason is because if you omit the parameter then php will do a loose comparison and use "type juggling" (a post of mine with manual references and a demo). A loose comparison when the needle is 0 will return the Jim Beam subarray's offset, and this is likely to be an unintended result.

  • Similarly, when you are processing the result from the multidimensional search, take the same care to differentiate between a false and a 0 result. Like with strpos() it is best perform a strict comparison like !==false or ===false depending on your usage.

answered Sep 16, 2017 at 23:38
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.