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

Posted

技术标签:

【中文标题】PHP多维数组搜索(按特定值查找键)【英文标题】:PHP Multidimensional Array Searching (Find key by specific value) 【发布时间】:2011-12-27 11:35:35 【问题描述】:

我有这个多维数组。我需要搜索它并只返回与“slug”的值匹配的键。我知道还有其他关于搜索多维数组的主题,但我对我的情况还不够了解。非常感谢您的帮助!

所以我需要一个类似的函数:

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

【问题讨论】:

你可以通过我在这里发布的课程来做到这一点:***.com/a/69304668/4276501 【参考方案1】:

另一个可能的解决方案是基于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 提供)可以在 DOCS 上找到。array_column()page。


更新

由于 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"
      ,...
]

我运行了 100 次搜索测试,为名称字段搜索不同的值,然后计算出平均时间(以 毫秒 为单位)。 Here你可以看一个例子。

结果是,在这个答案上提出的方法需要大约 2E-7 才能找到值,而接受的答案方法需要大约 8E-7。

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

更新二

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

更新 III

感谢@mickmackusa 发现此方法的一些限制:

此方法在关联键上会失败。 此方法仅适用于索引子数组(从 0 开始并具有连续升序的键)。

【讨论】:

有人知道这个的性能吗?看起来它最终会更慢,并且仍然需要 5.5。我在 5.4 上无法测试。 对于任何不明白的人:在 php 7 中,for 循环更快。当我在那个 eval.in 示例中更改为 5.6 时,array_search 稍微快了一点。 聪明!我正在做一些类似的事情,使用 array_combine() 和 array_column() 来创建另一个数组,用一个已知的键来获取我的数据,但这更优雅。 array_search()array_column() 一起使用将不适用于OP 的样本数组,因为子数组键从1 开始。此方法也将在关联键上失败。此方法仅适用于索引子数组(从0 开始并具有连续升序的键)。这样做的原因是因为array_column() 会在其返回的数组中生成新的索引。 完全正确@mickmackusa,我已将您的知识添加到答案中。感谢您的帮助【参考方案2】:

使用此功能:

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

【讨论】:

不错的答案。您可以在我的回答中查看您的提案的执行情况 只有代码的答案在 *** 上的价值很低。请更新您的帖子以解释您的叶节点子字符串搜索功能的工作原理。此方法并非专门设计为按照 OP 的要求工作,因此澄清差异很重要。演示链接将大大提高读者的理解力。始终发布旨在教育 OP 和更多 SO 受众的答案。【参考方案3】:

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

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

【讨论】:

【参考方案4】:

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

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

【讨论】:

没问题!只是为了节省您的时间,如果您尝试 josef answer,该函数将返回一个包含一个元素的数组。关键是想要的答案:) @Ivan josef 的回答与这个非常不同。你自己测试过吗。我一直在关注这个答案,但我认为它行不通,因为 array_walk_recursive 看不到一个级别。对于每个第一级键,josef 正在调用 strpos 或检查所有叶节点。看出区别了吗? 当然@mickmackusa 但是汉斯给出了某种灵感,答案不是字面上给出的解决方案。正如约瑟夫在他的回答中所做的那样,它需要更多的阐述。但是,您说得对,这个答案并不能完全解决问题。 不能正确解决所提问题的答案是“不正确的”,可能会误导/混淆研究人员。【参考方案5】:

试试这个

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;
    

【讨论】:

纯代码答案在 *** 上的价值很低。请更新您的帖子以解释您的递归方法的工作原理、合适的情况以及递归是不必要开销的情况。始终发布旨在教育 OP 和更多 SO 受众的答案。附:我认为大多数 php 开发人员会更喜欢 &&|| 而不是 ANDOR 在您的情况下。没有理由声明current_key$needle 的比较应该是严格的。【参考方案6】:

很简单:

function myfunction($products, $field, $value)

   foreach($products as $key => $product)
   
      if ( $product[$field] === $value )
         return $key;
   
   return false;

【讨论】:

如果您在条件语句中使用此函数,您将需要对类型进行绝对检查,因为返回的键有时可能具有 [0] 的索引。因此,如果进行条件检查,它应该看起来像这样:if (myfunction($array, 'field', 'value') !== FALSE )) // do something... 实现最佳性能和技术人员理解的简单解决方案。 谢谢。它简单可靠。我已经测试了这个和 , array_search($value, array_column($searchArray, $searchKey)) 替代方案。我从 array_search()/array_column 方法得到不正确的结果。【参考方案7】:
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; 
 

【讨论】:

只有代码的答案在 *** 上的价值很低。请更新您的帖子以解释您的递归方法的工作原理、合适的情况以及递归是不必要开销的情况。始终发布旨在教育 OP 和更多 SO 受众的答案。【参考方案8】:

该类方法可以通过多个条件在数组中搜索:

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"
  

【讨论】:

你好宿命论者***.com/questions/40860030/…。与这些问题有关,您能澄清一下这个问题吗

以上是关于PHP多维数组搜索(按特定值查找键)的主要内容,如果未能解决你的问题,请参考以下文章

检查多维数组的任何子数组中的特定键是不是存在特定值

如何按特定的子数组值对多维数组进行分组?

PHP - 在多维数组中查找键

具有未知键数的多维数组上的PHP Array_intersect

PHP多维数组搜索并获取键的数组[重复]

多维数组:如何获取特定键的所有值? [复制]