【问题标题】:PHP Multidimensional Array Searching (Find key by specific value)PHP多维数组搜索(按特定值查找键)
【发布时间】: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'    => '',
        ),
);

【问题讨论】:

标签: php search multidimensional-array key


【解决方案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));

【讨论】:

  • 不错的答案。您可以在我的回答中查看您的提案的执行情况
  • 只有代码的答案在 StackOverflow 上的价值很低。请更新您的帖子以解释您的叶节点子字符串搜索功能的工作原理。此方法并非专门设计为按照 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;
        }
    

    【讨论】:

    • 纯代码答案在 StackOverflow 上的价值很低。请更新您的帖子以解释您的递归方法的工作原理、合适的情况以及递归是不必要开销的情况。始终发布旨在教育 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; 
    } 
    

    【讨论】:

    • 只有代码的答案在 StackOverflow 上的价值很低。请更新您的帖子以解释您的递归方法的工作原理、合适的情况以及递归是不必要开销的情况。始终发布旨在教育 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"
      }
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-13
    • 2011-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-13
    相关资源
    最近更新 更多