Is there any fast way to get all subarrays where a key value pair was found in a multidimensional array? I can\'t say how deep the array will be.
Simple example arra
if (isset($array[$key]) && $array[$key] == $value)
A minor imporvement to the fast version.
<?php
$arr = array(0 => array("id"=>1,"name"=>"cat 1"),
1 => array("id"=>2,"name"=>"cat 2"),
2 => array("id"=>3,"name"=>"cat 1")
);
$arr = array_filter($arr, function($ar) {
return ($ar['name'] == 'cat 1');
//return ($ar['name'] == 'cat 1' AND $ar['id'] == '3');// you can add multiple conditions
});
echo "<pre>";
print_r($arr);
?>
Ref: http://php.net/manual/en/function.array-filter.php
If you want to search for array of keys this is good
function searchKeysInMultiDimensionalArray($array, $keys)
{
$results = array();
if (is_array($array)) {
$resultArray = array_intersect_key($array, array_flip($keys));
if (!empty($resultArray)) {
$results[] = $resultArray;
}
foreach ($array as $subarray) {
$results = array_merge($results, searchKeysInMultiDimensionalArray($subarray, $keys));
}
}
return $results;
}
Keys will not overwrite because each set of key => values will be in separate array in resulting array.
If you don't want duplicate keys then use this one
function searchKeysInMultiDimensionalArray($array, $keys)
{
$results = array();
if (is_array($array)) {
$resultArray = array_intersect_key($array, array_flip($keys));
if (!empty($resultArray)) {
foreach($resultArray as $key => $single) {
$results[$key] = $single;
}
}
foreach ($array as $subarray) {
$results = array_merge($results, searchKeysInMultiDimensionalArray($subarray, $keys));
}
}
return $results;
}
http://snipplr.com/view/51108/nested-array-search-by-value-or-key/
<?php
//PHP 5.3
function searchNestedArray(array $array, $search, $mode = 'value') {
foreach (new RecursiveIteratorIterator(new RecursiveArrayIterator($array)) as $key => $value) {
if ($search === ${${"mode"}})
return true;
}
return false;
}
$data = array(
array('abc', 'ffffd'),
'ccc',
'bbb',
array('aaa', array('yyy', 'mp' => 555))
);
var_dump(searchNestedArray($data, 555));
This is a revised function from the one that John K. posted... I need to grab only the specific key in the array and nothing above it.
function search_array ( $array, $key, $value )
{
$results = array();
if ( is_array($array) )
{
if ( $array[$key] == $value )
{
$results[] = $array;
} else {
foreach ($array as $subarray)
$results = array_merge( $results, $this->search_array($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_array($arr, 'name', 'cat 1'));
Be careful of linear search algorithms (the above are linear) in multiple dimensional arrays as they have compounded complexity as its depth increases the number of iterations required to traverse the entire array. Eg:
array(
[0] => array ([0] => something, [1] => something_else))
...
[100] => array ([0] => something100, [1] => something_else100))
)
would take at the most 200 iterations to find what you are looking for (if the needle were at [100][1]), with a suitable algorithm.
Linear algorithms in this case perform at O(n) (order total number of elements in entire array), this is poor, a million entries (eg a 1000x100x10 array) would take on average 500,000 iterations to find the needle. Also what would happen if you decided to change the structure of your multidimensional array? And PHP would kick out a recursive algorithm if your depth was more than 100. Computer science can do better:
Where possible, always use objects instead of multiple dimensional arrays:
ArrayObject(
MyObject(something, something_else))
...
MyObject(something100, something_else100))
)
and apply a custom comparator interface and function to sort and find them:
interface Comparable {
public function compareTo(Comparable $o);
}
class MyObject implements Comparable {
public function compareTo(Comparable $o){
...
}
}
function myComp(Comparable $a, Comparable $b){
return $a->compareTo($b);
}
You can use uasort()
to utilize a custom comparator, if you're feeling adventurous you should implement your own collections for your objects that can sort and manage them (I always extend ArrayObject to include a search function at the very least).
$arrayObj->uasort("myComp");
Once they are sorted (uasort is O(n log n), which is as good as it gets over arbitrary data), binary search can do the operation in O(log n) time, ie a million entries only takes ~20 iterations to search. As far as I am aware custom comparator binary search is not implemented in PHP (array_search()
uses natural ordering which works on object references not their properties), you would have to implement this your self like I do.
This approach is more efficient (there is no longer a depth) and more importantly universal (assuming you enforce comparability using interfaces) since objects define how they are sorted, so you can recycle the code infinitely. Much better =)