PHP Multidimensional Array Searching (Find key by

2019-01-01 10:42发布

问题:

I have this multidimensional array. I need to search it and return only the key that matches the value of the \"slug\". I know there are other threads about searching multidimensional arrays, but I\'m not really understanding enough to apply to my situation. Thanks very much for any help!

So I need a function like:

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

Here\'s the Array:

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

回答1:

Very simple:

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


回答2:

Another poossible solution is based on the array_search() function. You need to use PHP 5.5.0 or higher.

Example

$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

Explanation

The function array_search() has two arguments. The first one is the value that you want to search. The second is where the function should search. The function array_column() gets the values of the elements which key is \'uid\'.

Summary

So you could use it as:

array_search(\'breville-one-touch-tea-maker-BTM800XL\', array_column($products, \'slug\'));

or, if you prefer:

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

The original example(by xfoxawy) can be found on the DOCS.
The array_column() page.


Update

Due to Vael comment I was curious, so I made a simple test to meassure the performance of the method that uses array_search and the method proposed on the accepted answer.

I created an array which contained 1000 arrays, the structure was like this (all data was randomized):

[
      {
            \"_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\"
      },...
]

I ran the search test 100 times searching for different values for the name field, and then I calculated the mean time in milliseconds. Here you can see an example.

Results were that the method proposed on this answer needed about 2E-7 to find the value, while the accepted answer method needed about 8E-7.

Like I said before both times are pretty aceptable for an application using an array with this size. If the size grows a lot, let\'s say 1M elements, then this little difference will be increased too.

Update II

I\'ve added a test for the method based in array_walk_recursive which was mentionend on some of the answers here. The result got is the correct one. And if we focus on the performance, its a bit worse than the others examined on the test. In the test, you can see that is about 10 times slower than the method based on array_search. Again, this isn\'t a very relevant difference for the most of the applications.

Update III

Thanks to @mickmackusa for spotting several limitations on this method:

  • This method will fail on associative keys.
  • This method will only work on indexed subarrays (starting from 0 and have consecutively ascending keys).


回答3:

This class method can search in array by multiple conditions:

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

Will produce:

array(2) {
  [5]=>
  array(2) {
    [\"foo\"]=>
    string(5) \"test4\"
    [\"bar\"]=>
    string(4) \"baz1\"
  }
  [10]=>
  array(2) {
    [\"foo\"]=>
    string(5) \"test4\"
    [\"bar\"]=>
    string(4) \"baz1\"
  }
}


回答4:

Use this function:

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

}

and call function.

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


回答5:

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


回答6:

For the next visitor coming along: use the recursive array walk; it visits every \"leaf\" in the multidimensional array. Here\'s for inspiration:

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


回答7:

Try this

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


回答8:

I would do like below, where $products is the actual array given in the problem at the very beginning.

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