PHP array search for multiple key / value pairs

I have a list of arrays (for this example I use cell phones). I want to be able to search for multiple key / value pairs and return the index of the parent array.

For example, here is my array:

// $list_of_phones (array) Array ( [0] => Array ( [Manufacturer] => Apple [Model] => iPhone 3G 8GB [Carrier] => AT&T ) [1] => Array ( [Manufacturer] => Motorola [Model] => Droid X2 [Carrier] => Verizon ) ) 

I want to be able to do something like the following:

 // This is not a real function, just used for example purposes $phone_id = multi_array_search( array('Manufacturer' => 'Motorola', 'Model' => 'Droid X2'), $list_of_phones ); // $phone_id should return '1', as this is the index of the result. 

Any ideas or suggestions on how I can or should do this?

+8
arrays php multidimensional-array
source share
6 answers

Perhaps this will be useful:

  /** * Multi-array search * * @param array $array * @param array $search * @return array */ function multi_array_search($array, $search) { // Create the result array $result = array(); // Iterate over each array element foreach ($array as $key => $value) { // Iterate over each search condition foreach ($search as $k => $v) { // If the array element does not meet the search condition then continue to the next element if (!isset($value[$k]) || $value[$k] != $v) { continue 2; } } // Add the array element key to the result array $result[] = $key; } // Return the result array return $result; } // Output the result print_r(multi_array_search($list_of_phones, array())); // Array ( [0] => 0 [1] => 1 ) // Output the result print_r(multi_array_search($list_of_phones, array('Manufacturer' => 'Apple'))); // Array ( [0] => 0 ) // Output the result print_r(multi_array_search($list_of_phones, array('Manufacturer' => 'Apple', 'Model' => 'iPhone 6'))); // Array ( ) 

As the result shows, this function will return an array of all keys with elements that match all search criteria.

+9
source share

you can use array_intersect_key and array_intersect and array_search

check php manual_integer_array_array to get an array of elements with corresponding keys

and array_intesect php manual to get an array if elements with corresponding values

u can get the key value in an array using $array[key]

and get the key of the value in the array using array_search $key = array_search('green', $array);

php.net/manual/en/function.array-search.php

+5
source share

In the end, I did the following. It is not very, but it works very well. For those who read, feel free to update with DRYer's answer:

 // Variables for this example $carrier = 'Verizon'; $model = 'Droid X2'; $manufacturer = 'Motorola'; // The foreach loop goes through each key/value of $list_of_phones and checks // if the given value is found in that particular array. If it is, it then checks // a second parameter (model), and so on. foreach ($list_of_phones as $key => $object) { if ( array_search($carrier, $object) ) { if ( array_search($model, $object) ) { if ( array_search($manufacturer, $object) ) { // Return the phone from the $list_of_phones array $phone = $list_of_phones[$key]; } } } } 

It works like a charm.

+3
source share

This method works for a multidimensional array like yours:

 $test = array_intersect_key($list_of_phones, array(array("Manufacturer" => "Motorola", "Carrier" => "Verizon"))); 
0
source share

I expanded @MichaelRushton's code by adding support for different comparison operators:

 function multi_array_search ($array, $search) { $result = []; foreach ($array as $key => $value) { //iterate over each array element foreach ($search as $k => $v) { //iterate over each search condition $operator = $v[0]; $searchField = $v[1]; $searchVal = $v[2]; switch ($operator) { case '=': $cond = ($value[$searchField] != $searchVal); break; case '!=': $cond = ($value[$searchField] == $searchVal); break; case '>': $cond = ($value[$searchField] <= $searchVal); break; case '<': $cond = ($value[$searchField] >= $searchVal); break; case '>=': $cond = ($value[$searchField] < $searchVal); break; case '<=': $cond = ($value[$searchField] > $searchVal); break; } //if the array element does not meet the search condition then continue to the next element if ((!isset($value[$searchField]) && $value[$searchField] !== null) || $cond) { continue 2; } } $result[] = $key; //add the array element key to the result array } return $result; } //incoming data: $phonesList = [ 0 => [ 'Manufacturer' => 'Apple', 'Model' => 'iPhone 3G 8GB', 'Carrier' => 'AT&T', 'Cost' => 100000 ], 1 => [ 'Manufacturer' => 'Motorola', 'Model' => 'Droid X2', 'Carrier' => 'Verizon', 'Cost' => 120000 ], 2 => [ 'Manufacturer' => 'Motorola', 'Model' => 'Droid X2', 'Carrier' => 'Verizon', 'Cost' => 150000 ] ]; var_dump(multi_array_search($phonesList, [ ['=', 'Manufacturer', 'Motorola'], ['>', 'Cost', '130000'] ] )); //output: array(1) { [0]=> int(2) } 
0
source share

This is the same as @Boolean_Type, but slightly improved it.

 function multi_array_search($array, $search) { $result = array(); foreach ($array as $key => $val) { foreach ($search as $k => $v) { // We check if the $k has an operator. $operator = '='; if (preg_match('(<|<=|>|>=|!=|=)', $k, $m) === 1) { // We change the operator. $operator = $m[0]; // We trim $k to remove white spaces before and after. $k = trim(str_replace($m[0], '', $k)); } switch ($operator) { case '=': $cond = ($val[$k] != $v); break; case '!=': $cond = ($val[$k] == $v); break; case '>': $cond = ($val[$k] <= $v); break; case '<': $cond = ($val[$k] >= $v); break; case '>=': $cond = ($val[$k] < $sv); break; case '<=': $cond = ($val[$k] > $sv); break; } if (( ! isset($val[$k]) && $val[$k] !== null) OR $cond) { continue 2; } } $result[] = $key; } return $result; } 

That way you can just do a search like this:

 $keys = multi_array_search($phonesList, array( 'Manufacturer' => 'Motorola', 'Cost >' => '130000', )); 

If found, you will have an array of such indices: array(1, 25, 33) (This is just an example).

0
source share

All Articles