I have an array as follows
array(2) {
["operator"] => array(2) {
["qty"] => int(2)
["id"] => int(251)
}
["accessory209"] => array(2) {
["qty"] => int(1)
["id"] => int(209)
}
["accessory211"] => array(2) {
["qty"] => int(1)
["id"] => int(211)
}
}
I'm trying to find a way to verify an id value exists within the array and return bool. I'm trying to figure out a quick way that doesn't require creating a loop. Using the in_array function did not work, and I also read that it is quite slow.
In the php manual someone recommended using flip_array() and then isset(), but I can't get it to work for a 2-d array.
doing something like
if($array['accessory']['id'] == 211)
would also work for me, but I need to match all keys containing accessory -- not sure how to do that
Anyways, I'm spinning in circles, and could use some help. This seems like it should be easy. Thanks.
7 Answers 7
array_walk()
can be used to check whether a particular value is within the array; - it iterates through all the array elements which are passed to the function provided as second argument. For example, the function can be called as in the following code.
function checkValue($value, $key) {
echo $value['id'];
}
$arr = array(
'one' => array('id' => 1),
'two' => array('id' => 2),
'three' => array('id' => 3)
);
array_walk($arr, 'checkValue');
4 Comments
array_walk
which again will be passed to the callback function (i.e. this is the way to pass the id
to search for).This function is useful in_array(211, $array['accessory']);
It verifies the whole specified array to see if your value exists in there and returns true.
Comments
$map = array();
foreach ($arr as $v) {
$map[$v['id']] = 1;
}
//then you can just do this as when needed
$exists = isset($map[211]);
Or if you need the data associated with it
$map = array();
foreach ($arr as $k => $v) {
$map[$v['id']][$k] = $v;
}
print_r($map[211]);
Comments
<?php
//PHP 5.3 way to do it
function searchNestedArray(array $array, $search, $mode = 'value') {
foreach (new RecursiveIteratorIterator(new RecursiveArrayIterator($array)) as $key => $value) {
if ($search === ${${"mode"}})
return true;
}
return false;
}
$data = array(
array('abc', 'ddd'),
'ccc',
'bbb',
array('aaa', array('yyy', 'mp' => 555))
);
var_dump(searchNestedArray($data, 555));
Comments
I used a static method because i needed it in a class, but if you want you can use it as a simple function.
/**
* Given an array like this
* array(
* 'id' => "first",
* 'title' => "First Toolbar",
* 'class' => "col-md-12",
* 'items' => array(
* array(
* 'tipo' => "clientLink",
* 'id' => "clientLinkInsert"
* )
* )
* )
*
* and array search like this
* array("items", 0, "id")
*
* Find the path described by the array search, in the original array
*
* @param array $array source array
* @param array $search the path to the item es. ["items", 0, "tipo"]
* @param null|mixed $defaultIfNotFound the default value if the value is not found
*
* @return mixed
*/
public static function getNestedKey($array, $search, $defaultIfNotFound = null)
{
if( count($search) == 0 ) return $defaultIfNotFound;
else{
$firstElementSearch = self::array_kshift($search);
if (array_key_exists($firstElementSearch, $array)) {
if( count($search) == 0 )
return $array[$firstElementSearch];
else
return self::getNestedKey($array[$firstElementSearch], $search, $defaultIfNotFound);
}else{
return $defaultIfNotFound;
}
}
}
Comments
You can use
Arr::getNestedElement($array, $keys, $default = null)
from this library to get value from multidimensional array using keys specified like 'key1.key2.key3'
or ['key1', 'key2', 'key3']
and fallback to default value if no element was found. Using your example it will look like:
if (Arr::getNestedElement($array, 'accessory.id') == 211)
Comments
if there is a search based on a value in the array you can use the PHP array_filter which is intended for this purpose,
for retrieving sibling values like qty in your example
array_values(
array_filter(
$yourArray,
fn ($inner)=> $inner['id'] == 211
)
)[0]['qty'] ?? [];
or for retiring the inner array key like accessory209 in your example:
array_keys(
array_filter(
$yourArray,
fn ($inner)=> $inner['id'] == 211
)
)[0] ?? [];
array_walk_recursive
which would not require you to do a loop. However, that function does not work if yourkey
has an array value, as yours does. A loop maybe the only way. May I ask why without loops?operator
, the elements in the subarray are passed (i.e.qty
,id
) and you can check against them. Have a look at the example in the docs... But as the OP only wants to search forid
,array_walk
is indeed easier.