The key is already the ... ehm ... key
echo $array[20120504];
If you are unsure, if the key exists, test for it
$key = 20120504;
$result = isset($array[
array[$key] : null;
Minor addition:
$result = @$array[$key] ?: null;
One may argue, that @ is bad, but keep it serious: This is more readable and straight forward, isn't?
Update: With PHP7 my previous example is possible without the error-silencer
$result = $array[$key] ?? null;
Answer from KingCrunch on Stack OverflowThe key is already the ... ehm ... key
echo $array[20120504];
If you are unsure, if the key exists, test for it
$key = 20120504;
$result = isset($array[
array[$key] : null;
Minor addition:
$result = @$array[$key] ?: null;
One may argue, that @ is bad, but keep it serious: This is more readable and straight forward, isn't?
Update: With PHP7 my previous example is possible without the error-silencer
$result = $array[$key] ?? null;
array_search('20120504', array_keys($your_array));
Videos
Firstly, this could use a better description (in a comment) explaining what it does. I had to figure it out from the code. I think the description should probably be something like
// Searches $array for associative arrays which are supersets of $parameters.
// If $multipleResults it will return all matches in an array;
// otherwise just the first, in an array.
Secondly, names.
findValueisn't very descriptive. How aboutfindSupersets?$arraywould traditionally be called$haystackin PHP, since you're searching through it for matches to a predicate.$multipleResoultis a misspelling. Correcting the spelling and adjective-noun agreement we get$multipleResults, which is ok, although I personally would prefer to communicate an action:$returnAll.$suspicioushas the wrong connotations for this native English speaker. If something is suspicious, it means that I think there's something wrong with it. My preferred variable name for something which may or may not pass an acceptance test is$candidate.
Thirdly, since PHP has a dynamic type system I think it would be more idiomatic to return just the element if !$multipleResults, rather than wrapping it in an array.
Now, you specifically ask whether there's a simpler way to do it. I think that using booleans it can be simplified quite a bit by inverting the assumption. Rather than prove it acceptable, prove it not acceptable. Taking into account various of my suggestions above and refactoring I get:
foreach($haystack as $childArray){
$isCandidate = true;
foreach($parameters as $k => $p){
if(!array_key_exists($k,$childArray) || $childArray[$k] != $p){
$isCandidate = false;
break;
}
}
if($isCandidate){
if(!$multipleResults){
return $childArray;
}
$result[] = $childArray;
}
}
return $result;
It's a couple of years now since I used PHP, and I'm not sure offhand whether there are built-in functions to test whether $childArray contains $parameters as a subset, or to filter an array by a predicate. It may be that the whole function can be reduced to two calls to built-ins. If not, you could consider whether you want to factor it out as
function findMatch(array $haystack, $predicate, $returnAll = false) {
$results = []
foreach ($haystack as $element) {
if ($predicate($element)) {
if ($returnAll) return $element;
$results[] = $element;
}
}
return $results;
}
function isSuperset(array $candidate, array $subset) {
foreach ($subset as $k => $v) {
if (!isset($candidate[$k]) || $candidate[$k] != $v) return false;
}
return true;
}
linking the two with a lambda.
You don't need to call a second foreach loop and temporarily store partial matches (suspicious/candidates) as you go.
Use array_intersect_assoc() and sizeof() (or count()) to instantly identify qualifying subarrays.
Code: (Demo)
function findValue(array $array, array $terms, $get_all=false){
$term_count=sizeof($terms); // cache the element count of $terms
$results=[]; // establish empty array for print_r if no matches are found.
foreach($array as $subarray){
if(sizeof(array_intersect_assoc($subarray,$terms))==$term_count){ // qualifying subarray
if(!$get_all){
return $subarray; // end loop and return the single subarray
}else{
$results[]=$subarray;
}
}
}
return $results;
}
Code:
function search($array, $key, $value)
{
$results = array();
if (is_array($array)) {
if (isset($array[$key]) && $array[$key] == $value) {
$results[] = $array;
}
foreach ($array as $subarray) {
$results = array_merge($results, search($subarray, $key, $value));
}
}
return $results;
}
$arr = array(0 => array(id=>1,name=>"cat 1"),
1 => array(id=>2,name=>"cat 2"),
2 => array(id=>3,name=>"cat 1"));
print_r(search($arr, 'name', 'cat 1'));
Output:
Array
(
[0] => Array
(
[id] => 1
[name] => cat 1
)
[1] => Array
(
[id] => 3
[name] => cat 1
)
)
If efficiency is important you could write it so all the recursive calls store their results in the same temporary $results array rather than merging arrays together, like so:
function search($array, $key, $value)
{
$results = array();
search_r($array, $key, $value, $results);
return $results;
}
function search_r($array, $key, $value, &$results)
{
if (!is_array($array)) {
return;
}
if (isset($array[$key]) && $array[$key] == $value) {
$results[] = $array;
}
foreach ($array as $subarray) {
search_r($subarray, $key, $value, $results);
}
}
The key there is that search_r takes its fourth parameter by reference rather than by value; the ampersand & is crucial.
FYI: If you have an older version of PHP then you have to specify the pass-by-reference part in the call to search_r rather than in its declaration. That is, the last line becomes search_r($subarray, $key, $value, &$results).
How about the SPL version instead? It'll save you some typing:
// I changed your input example to make it harder and
// to show it works at lower depths:
$arr = array(0 => array('id'=>1,'name'=>"cat 1"),
1 => array(array('id'=>3,'name'=>"cat 1")),
2 => array('id'=>2,'name'=>"cat 2")
);
//here's the code:
$arrIt = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr));
foreach ($arrIt as $sub) {
$subArray = $arrIt->getSubIterator();
if ($subArray['name'] === 'cat 1') {
$outputArray[] = iterator_to_array($subArray);
}
}
What's great is that basically the same code will iterate through a directory for you, by using a RecursiveDirectoryIterator instead of a RecursiveArrayIterator. SPL is the roxor.
The only bummer about SPL is that it's badly documented on the web. But several PHP books go into some useful detail, particularly Pro PHP; and you can probably google for more info, too.