Recursive array_search - php

I have a multi-dimensional array:
$categories = array(
array(
'CategoryID' => 14308,
'CategoryLevel' => 1,
'CategoryName' => 'Alcohol & Food',
'CategoryParentID' => 14308
),
// CHILD CATEGORIES
array(
array(
'CategoryID' => 179836,
'CategoryLevel' => 2,
'CategoryName' => 'Alcohol & Alcohol Mixes',
'CategoryParentID' => 14308
),
array(
array(
'CategoryID' => 172528,
'CategoryLevel' => 2,
'CategoryName' => 'Antipasto, Savoury',
'CategoryParentID' => 14308
)
)
)
);
I need to get the exact location of the index, and since array_search doesn't work on multi-dimensional arrays, I'm using one of the functions provided on the PHP manual page.
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
.. but it also returns the key of the first array only:
echo recursive_array_search(172528, $categories); // outputs 1
I'm expecting:
[1][1][0]

You can change your recursive function like this, which should give you the solution:
function recursive_array_search($needle, $haystack, $currentKey = '') {
foreach($haystack as $key=>$value) {
if (is_array($value)) {
$nextKey = recursive_array_search($needle,$value, $currentKey . '[' . $key . ']');
if ($nextKey) {
return $nextKey;
}
}
else if($value==$needle) {
return is_numeric($key) ? $currentKey . '[' .$key . ']' : $currentKey . '["' .$key . '"]';
}
}
return false;
}
This will result in
[1][1][0]["CategoryID"]
Since CategoryID is also a key in your multidimensional array.
If you don't want this, you can adapt the function to
function recursive_array_search($needle, $haystack, $currentKey = '') {
foreach($haystack as $key=>$value) {
if (is_array($value)) {
$nextKey = recursive_array_search($needle,$value, $currentKey . '[' . $key . ']');
if ($nextKey) {
return $nextKey;
}
}
else if($value==$needle) {
return is_numeric($key) ? $currentKey . '[' .$key . ']' : $currentKey;
}
}
return false;
}

You are ignoring the returned value of your inner call to recursive_array_search. Don't do that.
/*
* Searches for $needle in the multidimensional array $haystack.
*
* #param mixed $needle The item to search for
* #param array $haystack The array to search
* #return array|bool The indices of $needle in $haystack across the
* various dimensions. FALSE if $needle was not found.
*/
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
if($needle===$value) {
return array($key);
} else if (is_array($value) && $subkey = recursive_array_search($needle,$value)) {
array_unshift($subkey, $key);
return $subkey;
}
}
}

public static function unique(array $data, $key){
$rez = [];
foreach($data as $val){
if(!isset($val[$key]) && is_array($val)){
return self::unique($val, $key);
}elseif( isset($val[$key]) ){
$rez[] = $val[$key];
}
}
return array_unique($rez);
}

function array_search_recursive( $search, $values = array(), $i = 0) {
$match = false;
var_dump($i, $search);
$i++;
foreach ( $values as $keyState => $val ) {
var_dump($val == $search, 'expression');
if ( $val == $search ) {
return $keyState;
}
if ( is_array( $val ) ) {
$match = array_search_recursive($search, $val, $i);
}
if ( $match !== false ) {
return $keyState;
}
}
return false;
}
echo array_search_recursive($search, $canada)
Edit:
This will return the first key, tested for $canada = array( 'Brazilia' => 'test1', "Alberta" => [ "Airdrie", "Brooks", "Camrose" ], "British Columbia" => [ "Abbotsford" => [ 'a', 'b', 'c' ], "Armstrong", "Castlegar" ], "Manitoba" => [ "Brandon", "Selkirk" ], 'Olanda' => 'test2' ); $search = "Selkirk";

Related

PHP - make multidimensional array to array of strings from the arrays names

I have a multidimensional array like this:
array (
level1 => array ( level1.1,
level1.2)
level2 => array ( level2.1,
level2.2 => array( level2.2.1 => 'foo',
level2.2.2 => 'bar',
level2.2.3 => 'test')
)
)
As a result I want an array of strings like this
array ("level1/level1.1",
"level1/level1.2",
"level2/level2.1",
"level2/level2.2/level2.2.1",
"level2/level2.2/level2.2.2",
"level2/level2.2/level2.2.3")
Here is the code I tried
function displayArrayRecursively($array, string $path) : array {
if($path == "")
$result_array = array();
foreach ($array as $key => $value) {
if (is_array($value)) {
$this->displayArrayRecursively($value, $path . $key . '/');
} else {
$result_array[] = $path . $key; }
}
return $result_array;
}
Any idea how I can achieve this. I could use a reference array to populate, but I want to solve it with return values.
$array = [
'level1' => [
'level1.1',
'level1.2'
],
'level2' => [
'level2.1',
'level2.2' => [
'level2.2.1' => 'foo',
'level2.2.2' => 'bar',
'level2.2.3' => 'test'
]
]
];
function arrayParser(array $array, ?string $path=null) {
$res = [];
foreach($array as $key => $value) {
if(is_array($value)) {
$res[] = arrayParser($value, ($path ? $path.'/' : $path).$key);
}
else {
$res[] = $path.'/'.(!is_numeric($key) ? $key : $value);
}
}
return flatten($res);
}
function flatten(array $array) {
$return = array();
array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; });
return $return;
}
$res = arrayParser($array); // result

PHP - Concatenate / cascade multidimensional array keys

I've realized I need to stop banging my head and ask for help...
I have the following array:
$permissionTypes = array(
'system' => array(
'view' => 'View system settings.',
'manage' => 'Manage system settings.'
),
'users' => array(
'all' => array(
'view' => 'View all users.',
'manage' => 'Manage all users.'
)
),
'associations' => array(
'generalInformation' => array(
'all' => array(
'view' => 'View general information of all associations.',
'manage' => 'Manage general information of all associations.'
),
'own' => array(
'view' => 'View general information of the association the user is a member of.',
'manage' => 'Manage general information of the association the user is a member of.'
)
)
));
I'm trying to collapse / cascade the keys into a one-dimension array like so:
array(
'system_view',
'system_manage',
'users_all_view',
'users_all_manage',
'associations_generalInformation_all_view',
'associations_generalInformation_all_manage',
'associations_generalInformation_own_view',
'associations_generalInformation_own_manage'
)
I could use nested loops, but the array will be an undefined number of dimensions.
This is the closest I've gotten:
public function iterateKeys(array $array, $joiner, $prepend = NULL) {
if (!isset($formattedArray)) { $formattedArray = array(); }
foreach ($array as $key => $value) {
if(is_array($value)) {
array_push($formattedArray, $joiner . $this->iterateKeys($value, $joiner, $key));
} else {
$formattedArray = $prepend . $joiner . $key;
}
}
return $formattedArray;
}
Any ideas?
I think this should do it:
public function iterateKeys(array $array, $joiner, $prepend = NULL) {
if (!isset($formattedArray)) {
$formattedArray = array();
}
foreach ($array as $key => $value) {
if(is_array($value)) {
$formattedArray = array_merge($formattedArray, $this->iterateKeys($value, $joiner, $prepend . $joiner . $key));
} else {
$formattedArray[] = $prepend . $joiner . $key;
}
}
return $formattedArray;
}
Since the recursive call returns an array, you need to use array_merge to combine it with what you currently have. And for the non-array case, you need to push the new string onto the array, not replace the array with a string.
try this:
function flattern(&$inputArray, $tmp = null, $name = '')
{
if ($tmp === null) {
$tmp = $inputArray;
}
foreach($tmp as $index => $value) {
if (is_array($value)) {
flattern($inputArray, $value, $name.'_'.$index);
if (isset($inputArray[$index])) {
unset($inputArray[$index]);
}
} else {
$inputArray[$name.'_'.$index] = $value;
}
}
return $inputArray;
}
var_dump(flattern($permissionTypes));
function flattenWithKeys(array $array, array $path = []) {
$result = [];
foreach ($array as $key => $value) {
$currentPath = array_merge($path, [$key]);
if (is_array($value)) {
$result = array_merge($result, flattenWithKeys($value, $currentPath));
} else {
$result[join('_', $currentPath)] = $value;
}
}
return $result;
}
$flattened = flattenWithKeys($permissionTypes);
Working fine for me.
function array_key_append($source_array, $return_array = array(), $last_key = '', $append_with = "#")
{
if(is_array($source_array))
{
foreach($source_array as $k => $v)
{
$new_key = $k;
if(!empty($last_key))
{
$new_key = $last_key . $append_with . $k;
}
if(is_array($v))
{
$return_array = array_key_append($v, $return_array, $new_key, $append_with);
} else {
$return_array[$new_key] = $v;
}
}
}
return $return_array;
}
$StandardContactRequestDataforALL = array_key_append($StandardContactRequestDataforALL, $return_array = array(), $last_key = '', $append_with = "#");

Search value in array from comma separated value in PHP

I have following array
Array
(
[0] => Array
(
[data] => PHP
[attribs] => Array
(
)
[xml_base] =>
[xml_base_explicit] =>
[xml_lang] =>
)
[1] => Array
(
[data] => Wordpress
[attribs] => Array
(
)
[xml_base] =>
[xml_base_explicit] =>
[xml_lang] =>
)
)
one varialbe like $var = 'Php, Joomla';
I have tried following but not working
$key = in_multiarray('PHP', $array,"data");
function in_multiarray($elem, $array,$field)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if($array[$bottom][$field] == $elem)
return true;
else
if(is_array($array[$bottom][$field]))
if(in_multiarray($elem, ($array[$bottom][$field])))
return true;
$bottom++;
}
return false;
}
so want to check if any value in $var is exists in array(case insensitive)
How can i do it without loop?
This should work for you:
(Put a few comments in the code the explain whats goning on)
<?php
//Array to search in
$array = array(
array(
"data" => "PHP",
"attribs" => array(),
"xml_base" => "",
"xml_base_explicit" => "",
"xml_lang" => ""
),
array(
"data" => "Wordpress",
"attribs" => array(),
"xml_base" => "",
"xml_base_explicit" => "",
"xml_lang" => "Joomla"
)
);
//Values to search
$var = "Php, Joomla";
//trim and strtolower all search values and put them in a array
$search = array_map(function($value) {
return trim(strtolower($value));
}, explode(",", $var));
//function to put all non array values into lowercase
function tolower($value) {
if(is_array($value))
return array_map("tolower", $value);
else
return strtolower($value);
}
//Search needle in haystack
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
//Search ever value in array
foreach($search as $value) {
if(in_array_r($value, array_map("tolower", array_values($array))))
echo $value . " found<br />";
}
?>
Output:
php found
joomla found
to my understanding , you are trying to pass the string ex : 'php' and the key : 'data' of the element .
so your key can hold a single value or an array .
$key = in_multiarray("php", $array,"data");
var_dump($key);
function in_multiarray($elem, $array,$field)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if(is_array($array[$bottom][$field]))
{
foreach($array[$bottom][$field] as $value)
{
if(strtolower(trim($value)) == strtolower(trim($elem)))
{
return true;
}
}
}
else if(strtolower(trim($array[$bottom][$field])) == strtolower(trim($elem)))
{
return true;
}
$bottom++;
}
return false;
}

Recursive search return all keys where value is present

Currently stuck trying to get the last part working, wanting to get all array keys returned where the value exists.
Test data
$testArr = array(
'id' => '249653315914',
'title' => 'testing',
'description' => 'testing',
'usernames' => array('jake', 'liam', 'john'),
'masterNames' => array('jake'),
'data' => array(
'aliases' => array(
'jake'
)
)
);
Method
recursive_search('jake', $testArr);
function recursive_search($needle, $haystack, $child = false) {
$values = array();
foreach($haystack as $key => $value) {
$current_key = $key;
if($needle === $value OR (is_array($value) && $children = recursive_search($needle, $value, true) !== false)) {
if($child) {
if($needle == $value) {
return true;
}
echo "children: $child, current_key: $current_key ";
return $current_key;
}
echo "current_key: $current_key, key: $key <br>";
$values[] = $current_key;
}
}
if(!empty($values)) {
return $values;
}
return false;
}
Output
current_key: usernames, key: usernames
current_key: masterNames, key: masterNames
children: 1, current_key: aliases current_key: data, key: data
array (size=3)
0 => string 'usernames' (length=5)
1 => string 'masterNames' (length=8)
2 => string 'data' (length=4)
Expected
array(
'usernames',
'masterNames',
'data' => array('aliases')
)
I'm losing track on the $child part I think, somewhere I should be returning something and assigning it but I think I've looked at this to long and overlooking the obvious.
Any help is awesome.
$testArr = array(
'id' => '249653315914',
'title' => 'jake',
'description' => 'testing',
'usernames' => array('jake', 'liam', 'john'),
'masterNames' => array('jake'),
'data' => array(
'aliases' => array(
'jake'
),
'aliases2' => array('level3' => array('jake'))
)
);
function recursive_search($needle, $haystack) {
$return = array();
if (is_array($haystack))
foreach($haystack as $key => $value)
{
if (is_array($value))
{
$child = recursive_search($needle, $value);
if (is_array($child) && !empty($child))
$return = array_merge($return, array($key => $child));
elseif ($child) $return[] = $key;
}
elseif ($value === $needle)
if (is_integer($key))
return true;
else
$return[] = $key;
}
elseif ($haystack === $needle)
return true;
return $return;
}
Output
Array
(
[0] => title
[1] => usernames
[2] => masterNames
[data] => Array
(
[0] => aliases
[aliases2] => Array
(
[0] => level3
)
)
)
Testing is needed, no warranty that it will work in all cases. Also, in the cases like this array('level3' => array('jake'), 'jake'), it will not go deeper to level3 and so on, as 'jake' is present in the original array. Please mention if that is not a desired behavior.
Edit by Bankzilla: To work with objects
function recursive_search($needle, $haystack) {
$return = array();
if (is_array($haystack) || is_object($haystack)) {
foreach($haystack as $key => $value) {
if (is_array($value) || is_object($value)) {
$child = recursive_search($needle, $value);
if ((is_array($child) || is_object($child)) && !empty($child)) {
$return = array_merge($return, array($key => $child));
} elseif ($child) {
$return[] = $key;
}
}
elseif ($value === $needle) {
if (is_integer($key)) {
return true;
} else {
$return[] = $key;
}
}
}
} elseif ($haystack === $needle) {
return true;
}
return $return;
}
the things I thought you did wrong was checking for if current $value is an array and doing a recursive search on it, while doing nothing with the return value of it (which should be the array either false ) , here I used a more step by step approach (well at least I thought so )
this works for a "tree with more branches"
EDIT
function recursive_search($needle, $haystack) {
$values = array();
foreach($haystack as $key => $value) {
if(is_array($value)) {
$children = $this->recursive_search($needle, $value);
if($children !== false){
if(!is_bool($children) and !empty($children)){
$key = array($key => $children);
}
$values[] = $key;
}
} else if(strcmp($needle, $value) == 0 ){
if(is_int($key))
return true;
else
$vaues[] = $key;
}
}
if(!empty($values)) {
return $values;
}
return false;
}
got rid of the "0"s in the array, thx Cheery for the hint (from his response)

Search_array in nested arrays

I've got an array with nested arrays, and I was trying to use the *search_array* function to sift through the array and give me back their keys. It hasn't been working. Here's the code:
<?php
$array = array(
'cat1' => array(1,2,3),
'cat2' => array(4,5,6),
'cat3' => array(7,8,9),
);
foreach($array as $cat){
if(is_array($cat)
echo array_search(5,$cat); //want it to return 'cat2'
else
echo array_search(5,$array);
}
Thanks!
If you always have a two-dimensional array, then it is as easy as:
function find($needle, $haystack) {
foreach($haystack as $key=>$value){
if(is_array($value) && array_search($needle, $value) !== false) {
return $key;
}
}
return false;
}
$cat = find(5, $array);
function mySearch($haystack, $needle, $index = null)
{
$aIt = new RecursiveArrayIterator($haystack);
$it = new RecursiveIteratorIterator($aIt);
while($it->valid())
{
if (((isset($index) AND ($it->key() == $index)) OR (!isset($index))) AND ($it->current() == $needle)) {
return $aIt->key();
}
$it->next();
}
return false;
}
$array = array(
'cat1' => array(1,2,3),
'cat2' => array(4,5,6),
'cat3' => array(7,8,9),
);
echo $arr_key = mySearch($array, 5);
this will give u the answer

Categories