PHP 多维数组搜索(按特定值查找键)

我有一个多维数组。我需要搜索它,只返回与“蛞蝓”值相匹配的键。我知道还有其他关于搜索多维数组的线程,但是我还没有真正理解到足以应用于我的情况。非常感谢您的帮助!

所以我需要一个像这样的函数:

myfunction($products,'breville-one-touch-tea-maker-BTM800XL');
// returns 1

下面是数组:

$products = array (
1  => array(
'name'          => 'The Breville One-Touch Tea Maker',
'slug'          => 'breville-one-touch-tea-maker-BTM800XL',
'shortname'     => 'The One-Touch Tea Maker',
'listprice'     => '299.99',
'price'         => '249.99',
'rating'        => '9.5',
'reviews'       => '81',
'buyurl'        => 'http://www.amazon.com/The-Breville-One-Touch-Tea-Maker/dp/B003LNOPSG',
'videoref1'     => 'xNb-FOTJY1c',
'videoref2'     => 'WAyk-O2B6F8',
'image'         => '812BpgHhjBML.jpg',
'related1'      => '2',
'related2'      => '3',
'related3'      => '4',
'bestbuy'       => '1',
'quote'         => '',
'quoteautor'    => 'K. Martino',
),


2  => array(
'name'          => 'Breville Variable-Temperature Kettle BKE820XL',
'slug'          => 'breville-variable-temperature-kettle-BKE820XL',
'shortname'     => 'Variable Temperature Kettle',
'listprice'     => '199.99',
'price'         => '129.99',
'rating'        => '9',
'reviews'       => '78',
'buyurl'        => 'http://www.amazon.com/Breville-BKE820XL-Variable-Temperature-1-8-Liter-Kettle/dp/B001DYERBK',
'videoref1'     => 'oyZWBD83xeE',
'image'         => '41y2B8jSKmwL.jpg',
'related1'      => '3',
'related2'      => '4',
'related3'      => '5',
'bestbuy'       => '1',
'quote'         => '',
'quoteautor'    => '',
),
);
265201 次浏览

很简单:

function myfunction($products, $field, $value)
{
foreach($products as $key => $product)
{
if ( $product[$field] === $value )
return $key;
}
return false;
}

此类方法可以根据多个条件在数组中进行搜索:

class Stdlib_Array
{
public static function multiSearch(array $array, array $pairs)
{
$found = array();
foreach ($array as $aKey => $aVal) {
$coincidences = 0;
foreach ($pairs as $pKey => $pVal) {
if (array_key_exists($pKey, $aVal) && $aVal[$pKey] == $pVal) {
$coincidences++;
}
}
if ($coincidences == count($pairs)) {
$found[$aKey] = $aVal;
}
}


return $found;
}
}


// Example:


$data = array(
array('foo' => 'test4', 'bar' => 'baz'),
array('foo' => 'test',  'bar' => 'baz'),
array('foo' => 'test1', 'bar' => 'baz3'),
array('foo' => 'test',  'bar' => 'baz'),
array('foo' => 'test',  'bar' => 'baz4'),
array('foo' => 'test4', 'bar' => 'baz1'),
array('foo' => 'test',  'bar' => 'baz1'),
array('foo' => 'test3', 'bar' => 'baz2'),
array('foo' => 'test',  'bar' => 'baz'),
array('foo' => 'test',  'bar' => 'baz'),
array('foo' => 'test4', 'bar' => 'baz1')
);


$result = Stdlib_Array::multiSearch($data, array('foo' => 'test4', 'bar' => 'baz1'));


var_dump($result);

将产生:

array(2) {
[5]=>
array(2) {
["foo"]=>
string(5) "test4"
["bar"]=>
string(4) "baz1"
}
[10]=>
array(2) {
["foo"]=>
string(5) "test4"
["bar"]=>
string(4) "baz1"
}
}
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;
}

另一种可能的解决方案是基于 array_search()函数。你 需要使用 PHP 5.5.0或更高。

例子

$userdb=Array
(
(0) => Array
(
(uid) => '100',
(name) => 'Sandra Shush',
(url) => 'urlof100'
),


(1) => Array
(
(uid) => '5465',
(name) => 'Stefanie Mcmohn',
(pic_square) => 'urlof100'
),


(2) => Array
(
(uid) => '40489',
(name) => 'Michael',
(pic_square) => 'urlof40489'
)
);


$key = array_search(40489, array_column($userdb, 'uid'));


echo ("The key is: ".$key);
//This will output- The key is: 2

解释

函数‘ array _ search ()’有两个参数。第一个是要搜索的值。第二个是函数应该搜索的位置。函数‘ array _ column ()’获取键为“ uid”的元素的值。

摘要

所以你可以把它当作:
array_search('breville-one-touch-tea-maker-BTM800XL', array_column($products, 'slug'));

或者,如果你愿意的话:

// define function
function array_search_multidim($array, $column, $key){
return (array_search($key, array_column($array, $column)));
}


// use it
array_search_multidim($products, 'slug', 'breville-one-touch-tea-maker-BTM800XL');

原始示例(通过 xfoxawy)可以在 医生上找到。
array_column() 呼叫.


更新

由于 Vael 的评论,我很好奇,所以我做了一个简单的测试来测量使用 array_search的方法的性能,以及在接受的答案上提出的方法。

我创建了一个包含1000个数组的数组,结构如下(所有数据都是随机的) :

[
{
"_id": "57fe684fb22a07039b3f196c",
"index": 0,
"guid": "98dd3515-3f1e-4b89-8bb9-103b0d67e613",
"isActive": true,
"balance": "$2,372.04",
"picture": "http://placehold.it/32x32",
"age": 21,
"eyeColor": "blue",
"name": "Green",
"company": "MIXERS"
},...
]

我对 name 字段的不同值进行了100次搜索测试,然后计算了 毫秒中的平均时间。你可以看到一个例子。

结果表明,提出的方法需要约2E-7来求值,而公认的方法需要约8E-7来求值。

正如我之前所说的,对于使用这种大小的数组的应用程序来说,这两种情况都是可以接受的。如果大小增加很多,比如说1M 个元素,那么这个小的差异也会增加。

更新二

我已经添加了一个基于 array_walk_recursive的方法测试,这里提到了一些答案。得到的结果是正确的。如果我们把注意力放在性能上,它比 测试上的其他测试结果要差一些。在测试中,您可以看到这比基于 array_search的方法慢了大约10倍。同样,对于大多数应用程序来说,这并不是一个非常相关的区别。

更新 III

感谢@mickmackusa 发现了这种方法的一些局限性:

  • 此方法将在关联键上失败。
  • 这个方法只能在索引子数组上工作(从0开始,并且有连续的升序键)。

更新 III 须知

  • 不考虑性能: 你可以使用 array _ merge 和 array _ keys & array _ column 来克服这个限制,比如:
$product_search_index =
array_search( 'breville-one-touch-tea-maker-BTM800XL', array_filter( array_combine( array_keys($products), array_column( $products, 'slug' ) ) ) );

试试这个

function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle==$value['uid'] OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}

对于下一个访问者: 使用递归数组遍历; 它访问多维数组中的每个“叶子”。以下是给你的启示:

function getMDArrayValueByKey($a, $k) {
$r = [];
array_walk_recursive ($a,
function ($item, $key) use ($k, &$r) {if ($key == $k) $r[] = $item;}
);
return $r;
}

使用此功能:

function searchThroughArray($search,array $lists){
try{
foreach ($lists as $key => $value) {
if(is_array($value)){
array_walk_recursive($value, function($v, $k) use($search ,$key,$value,&$val){
if(strpos($v, $search) !== false )  $val[$key]=$value;
});
}else{
if(strpos($value, $search) !== false )  $val[$key]=$value;
}


}
return $val;


}catch (Exception $e) {
return false;
}
}

和调用函数。

print_r(searchThroughArray('breville-one-touch-tea-maker-BTM800XL',$products));

我想在下面这样做,其中 $products是问题一开始给出的实际数组。

print_r(
array_search("breville-variable-temperature-kettle-BKE820XL",
array_map(function($product){return $product["slug"];},$products))
);

您可以将数组转换为 JSON 并以字符串的形式进行搜索,然后返回找到的对象,因此无论嵌套多深,它都会很快找到:

function findObjectByKeyValue($array, $key, $value){
$object = [];
$string = json_encode($array);
$foundPosition = strpos($string, '"' . $key . '":"' . $value . '"');


if( $foundPosition ){
$prevBracketPos = strrpos(substr($string, 0, $foundPosition), '{');


if( $prevBracketPos ){
$nextBracketPos = strpos($string, '}', $foundPosition);


if( $nextBracketPos ){
$brackets = 0;


while( strpos(substr($string, $foundPosition, $nextBracketPos - $foundPosition), '{') &&
substr_count(substr($string, $foundPosition, $nextBracketPos - $foundPosition), '{') > $brackets
){
$lenToAdd = strlen(substr($string, $foundPosition, $nextBracketPos - $foundPosition + 1));
$nextBracketPos = strpos($string, '}', $foundPosition + $lenToAdd);
$brackets++;
}


$substr = substr($string, $prevBracketPos, $nextBracketPos - $prevBracketPos + 1);


// Confirm it's wrapped with brackets before we decode
if( substr($substr, 0, 1) === '{' && substr($substr, -1, 1) === '}' ){
$object = json_decode($substr, true);
}
}
}
}


return $object;
}

例如:

$arr = [{
"items":
{
"1": [
{
"id": "621eaf06062cd",
"nestedItem":
{
"id": "123",
"nestedItem":
{
"id": "456",
"nestedItem":
{
"id": "789"
}
}
}
}],
"2": [
{
"id": "621eb58de7364",
}],
"3": [
{
"id": "62226910716af",
}]
}
}];
echo findObjectByKeyValue($arr, 'id', '123');
/* {
"id": "123",
"nestedItem":
{
"id": "456",
"nestedItem":
{
"id": "789"
}
}
} /*
echo findObjectByKeyValue($arr, 'id', '621eaf06062cd');
/* {
"id": "621eaf06062cd",
"nestedItem":
{
"id": "123",
"nestedItem":
{
"id": "456",
"nestedItem":
{
"id": "789"
}
}
}
} */


您可能遇到的唯一问题是数组中是否有括号作为字符串。

适用于关联数组:

public function getKeyByParamValue(string $param, mixed $value, array $array): mixed
{
$keys = $this->getKeysByParamValue($param, $value, $array);


return empty($keys) ? null : $keys[0];
}


public function getKeysByParamValue(string $param, mixed $value, array $array): ?array
{
return array_keys(
array_combine(
array_keys($array),
array_column($array, $param)
),
$value
);
}