如何在PHP中用multidimensional array中的key =>值进行search

有没有什么快速的方法来获取所有在一个multidimensional array中find一个键值对的子数组? 我不能说这个arrays有多深。

简单的示例数组:

$arr = array(0 => array(id=>1,name=>"cat 1"), 1 => array(id=>2,name=>"cat 2"), 2 => array(id=>3,name=>"cat 1") ); 

当我searchkey = name和value =“cat 1”时,函数应该返回:

 array(0 => array(id=>1,name=>"cat 1"), 1 => array(id=>3,name=>"cat 1") ); 

我想这个函数必须recursion才能达到最深的水平。

码:

 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')); 

输出:

 Array ( [0] => Array ( [id] => 1 [name] => cat 1 ) [1] => Array ( [id] => 3 [name] => cat 1 ) ) 

如果效率很重要,可以编写它,这样所有的recursion调用都将结果存储在相同的临时$results数组中,而不是将数组合并在一起,如下所示:

 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); } } 

关键在于search_r通过引用而不是按值来获取第四个参数。 &符号是至关重要的。

仅供参考:如果您有较旧版本的PHP,则必须在调用 search_r而不是声明中指定传递引用部分。 也就是说,最后一行变成search_r($subarray, $key, $value, &$results)

SPL版本呢? 这将节省您一些打字:

 // 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); } } 

最棒的是基本上相同的代码将通过使用RecursiveDirectoryIterator而不是RecursiveArrayIterator来遍历目录。 SPL是roxor。

对于SPL来说,唯一令人失望的是它在networking上的logging很糟糕。 但是一些PHP书籍进入了一些有用的细节,特别是Pro PHP; 你也可以谷歌更多的信息。

 <?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); ?> 

参考: http : //php.net/manual/en/function.array-filter.php

回过头来发布这个更新的任何人需要对这些答案的优化技巧,特别是约翰·库格尔曼的上面的伟大答案。

他的发布function工作正常,但我不得不优化这种情况下处理12 000行结果集。 这个function需要8秒钟才能完成所有logging,太长了。

我只是需要停止search的function,并find匹配时返回。 也就是说,如果searchcustomer_id,我们知道在结果集中只有一个,一旦findmultidimensional array中的customer_id,我们就要返回。

这是速度优化(和简化)版本的这个function,为有需要的人。 与其他版本不同的是,它只能处理一个数组深度,不会recursion并合并多个结果。

 // search array for specific key = value public function searchSubArray(Array $array, $key, $value) { foreach ($array as $subarray){ if (isset($subarray[$key]) && $subarray[$key] == $value) return $subarray; } } 

这就减less了将12 000条logging匹配到1.5秒的任务。 仍然非常昂贵,但更合理。

 if (isset($array[$key]) && $array[$key] == $value) 

对快速版本的轻微改进。

在multidimensional array中,要小心线性searchalgorithm(以上是线性searchalgorithm),因为它们的复杂度随着深度增加遍历整个数组所需的迭代次数而变得复杂。 例如:

 array( [0] => array ([0] => something, [1] => something_else)) ... [100] => array ([0] => something100, [1] => something_else100)) ) 

最多需要200次迭代才能find你正在寻找的东西(如果针头处于[100] [1]),那么使用合适的algorithm。

在这种情况下,线性algorithm在O(n)(整个arrays中的元素的总数)上执行,这是不好的,一百万个条目(例如1000×100×10个arrays)平均需要500,000次迭代才能find针。 另外如果你决定改变multidimensional array的结构会发生什么? 如果你的深度超过100,那么PHP将推出一个recursionalgorithm。计算机科学可以做得更好:

如有可能,请始终使用对象而不是multidimensional array:

 ArrayObject( MyObject(something, something_else)) ... MyObject(something100, something_else100)) ) 

并应用自定义比较器接口和函数进行sorting和查找:

 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); } 

你可以使用uasort()来利用一个自定义的比较器,如果你觉得冒险的话,你应该为你的对象实现你自己的集合,这些集合可以对它们进行sorting和pipe理(我总是扩展ArrayObject以至less包含一个search函数)。

 $arrayObj->uasort("myComp"); 

一旦它们被sorting(uasort是O(n log n),就像它处理任意数据一样好),二进制search可以在O(log n)时间进行操作,即一百万个条目只需要20次迭代search。 据我所知,自定义比较二进制search没有在PHP中实现( array_search()使用自然sorting,对对象引用,而不是它们的属性),你将不得不像我一样实现这个你自己。

这种方法更高效(不再有深度),更重要的是通用(假设你使用接口强制进行比较),因为对象定义了它们是如何sorting的,所以你可以无限地回收代码。 好多了=)

 $result = array_filter($arr, function ($var) { $found = false; array_walk_recursive($var, function ($item, $key) use (&$found) { $found = $found || $key == "name" && $item == "cat 1"; }); return $found; }); 

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', 'ddd'), 'ccc', 'bbb', array('aaa', array('yyy', 'mp' => 555)) ); var_dump(searchNestedArray($data, 555)); 
 function in_multi_array($needle, $key, $haystack) { $in_multi_array = false; if (in_array($needle, $haystack)) { $in_multi_array = true; }else { foreach( $haystack as $key1 => $val ) { if(is_array($val)) { if($this->in_multi_array($needle, $key, $val)) { $in_multi_array = true; break; } } } } return $in_multi_array; } 

我需要类似的东西,但是要按价值searchmultidimensional array…我拿了约翰的例子,写了

 function _search_array_by_value($array, $value) { $results = array(); if (is_array($array)) { $found = array_search($value,$array); if ($found) { $results[] = $found; } foreach ($array as $subarray) $results = array_merge($results, $this->_search_array_by_value($subarray, $value)); } return $results; } 

我希望它有助于某人:)

这是John K.发布的函数的一个修改后的函数…我只需要抓取数组中的特定键,而不是上面的键。

 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')); 

这里是解决scheme:

 <?php $students['e1003']['birthplace'] = ("Mandaluyong <br>"); $students['ter1003']['birthplace'] = ("San Juan <br>"); $students['fgg1003']['birthplace'] = ("Quezon City <br>"); $students['bdf1003']['birthplace'] = ("Manila <br>"); $key = array_search('Delata Jona', array_column($students, 'name')); echo $key; ?> 

另一个版本从数组元素中返回键值(无recursion,速度优化):

 // if the array is $arr['apples'] = array('id' => 1); $arr['oranges'] = array('id' => 2); //then print_r(search_array($arr, 'id', 2); // returns Array ( [oranges] => Array ( [id] => 2 ) ) // instead of Array ( [0] => Array ( [id] => 2 ) ) // search array for specific key = value function search_array($array, $key, $value) { $return = array(); foreach ($array as $k=>$subarray){ if (isset($subarray[$key]) && $subarray[$key] == $value) { $return[$k] = $subarray; return $return; } } } 

感谢所有在这里发布的人。

 function findKey($tab, $key){ foreach($tab as $k => $value){ if($k==$key) return $value; if(is_array($value)){ $find = findKey($value, $key); if($find) return $find; } } return null; }