I need a php function that will recursively search an array on the basis of key I provided. and want to get an array as return output containing all the values those are mapped with the searched key.
For e.g.:
[Case] => Array
(
[0] => Array
(
[CASE_ID] => 2233
[CHECK_ID] => 57
[CLIENT_ID] => 78
)
[2] => Array
(
[CASE_ID] => 9542
[CHECK_ID] => 45
[CLIENT_ID] => 18
)
)
If I would pass this array and key CHECK_ID, then it should return me an array containing 57,45. Kindly ask if you need more explanation. Thanks in Advance.
Walking the array and chucking found keys into a new one:
function find_matches($array, $value) {
$found = array();
array_walk_recursive($array,
function ($item, $key) use ($value, &$found) {
if ($value === $key) {
$found[] = $item;
}
}
);
return $found;
}
see http://codepad.viper-7.com/dVmYOT
Have you also considered using find('list') with a fields condition restriction?
Just check each element, filter based on key, convert the outcome to an array:
$filter = function($c, $key) {
return $key === 'CHECK_ID';
};
$filtered = new CallbackFilterIterator(
new RecursiveIteratorIterator(
new RecursiveArrayIterator($array)
),
$filter
);
var_dump(iterator_to_array($filtered, false));
Result:
array(2) {
[0] =>
int(57)
[1] =>
int(45)
}
function array_rfind($find, $arr) {
$found = array();
foreach($arr as $key => $val) {
if($key == $find)
$found[] = $val;
elseif(is_array($val))
$found = array_merge($found, array_rfind($find, $val));
}
return $found;
}
Related
Let's say I have an array like this
Array
(
[0] => 123
[180] => Array
(
[400] => Array
(
[0] => 474
[1] => 395
[2] => 994
[3] => 365
)
)
[1] => 144
[2] => 119
)
I would like to go though this array and generate a one dimensional array that contains all the numbers. In the loop, if we get an array, then the number is the corresponding array key.
I did something like this but it doesn't work:
function flatten_array($data) {
$result = array();
foreach ($data as $key => $value) {
if(is_array($value)) {
$result[] = $key;
flatten_array($value);
} else {
$result[] = $value;
}
}
return $result;
}
The resulting array I should get should be this one:
$result = Array
(
[0] => 123
[1] => 180
[2] => 400
[3] => 474
[4] => 395
[5] => 994
[6] => 365
[7] => 144
[8] => 119
)
Any help will be appreciated thanks.
There are some helpful libraries in composer, for example this one: https://packagist.org/packages/nikic/iter
With this lib you can flatten the data the following way:
$result = toArray(flatten($data));
Without using libraries, such result can be achieved this way:
function flattenArray(array $data) {
$values = array_values($data);
$result = [];
foreach ($values as $value) {
if (is_array($value)) {
$result = array_merge(flattenArray($value), $result);
} else {
$result[] = $value;
}
}
return $result;
}
P.S. Note the mistake in your original example:
$result[] = $key;
flatten_array($value);
You call the recursive function without using its returned result.
And you assign the key instead.
Your code doesn't accumulate a result anywhere. You could return arrays and merge them, but to save allocation overhead I recommend using a single result array and passing it by reference into your recursive walk function. Here's a complete example:
function flatten_array($a) {
function flatten($a, &$flat) {
foreach ($a as $k => $v) {
if (is_array($v)) {
$flat[] = $k;
flatten($v, $flat);
}
else {
$flat[] = $v;
}
}
}
$flat = [];
flatten($a, $flat);
return $flat;
}
$a = [
123,
180 => [
400 => [
474,
395,
994,
365,
]
],
144,
119
];
print_r(flatten_array($a));
If you expect your depth to be massive, you can do it iteratively to avoid an overflow. Note that this gives a breadth-first ordering:
function flatten_array($a) {
$flat = [];
for ($stack = [$a]; count($stack);) {
foreach (array_pop($stack) as $k => &$v) {
if (is_array($v)) {
$flat[] = $k;
$stack[] = $v;
}
else {
$flat[] = $v;
}
}
}
return $flat;
}
You can use next recursive function:
function array_flat($arr) {
$res = [];
foreach($arr as $key=>$val) {
if (is_array($val)) {
// element is array: Push key to result and merge recursion result
array_push($res, $key);
$res = array_merge($res, array_flat($val));
} else {
// push simple value to result
array_push($res, $val);
}
}
return $res;
}
print_r(array_flat($arr));
Try working PHP code o PHPize.online
I'm getting below output as an array.
$array =
Array
(
[12] => Array
(
[1] => Array
(
[14] => Array
(
[0] => Array
(
[name] => Avaya Implementation Services
[service_id] => 14
[ser_type_id] => 1
[service_desc] =>Avaya Implementation Servic
)
)
)
)
);
I want to print only service_desc array value. and I don't want call like $array[12][1][14][0]['service_desc'];
How can I call particular service_desc array value of the array?
As you mentioned that you don't want to call it as $array[12][1][14][0]['service_desc'] you can use extract function which will create variables from your array,
extract($array[12][1][14][0]);
echo $service_desc;
And then you can use your particular key such as service_desc as variable.
You can try this function: (Please optimize as per your requirements)
$arr ="<YOUR ARRAY>";
$val = "service_desc";
echo removekey($arr, $val);
function removekey($arr, $val) {
$return = array();
foreach ($arr as $k => $v) {
if (is_array($v) && $k !== $val) {
removekey($v, $val);
continue;
}
if ($k == $val) {
echo ($arr[$k]);
die;
}
$return[$k] = $v;
}
return $return;
}
You can use array_walk_rescursive to frame a single dimensional array of matching keys:
DEMO
<?php
$array[12][1][14][0]['service_desc'] = 'Avaya Implementation Servic';
$array[12][1][14][0]['service'] = 'dsfasf';
$array[12][1][114][0]['service_desc'] = 'Avaya Implementation Servicasdfdsf';
$searchKey = 'service_desc';
$desiredValues = [];
array_walk_recursive($array, function ($v, $k) use ($searchKey, &$desiredValues) {
if ($k === $searchKey) {
$desiredValues[] = $v;
}
});
print_r($desiredValues);
So this will yield:
Array
(
[0] => Avaya Implementation Servic
[1] => Avaya Implementation Servicasdfdsf
)
You might use the array_walk_recursive function.
array_walk_recursive($array, function ($val, $key) {
if ($key == 'service_desc') print_r($val);
} );
Instead of the print_r statement, you can collect your data into another structure, which you convey using the use statement, or with the $userdata additional parameter (see http://www.php.net/manual/en/function.array-walk-recursive.php ).
$results = array();
array_walk_recursive($array, function ($val, $key) use (&$results) {
if ($key == 'service_desc') {
$results []= $val;
}
} );
Pay extra care to the & in front of the use (&$results) otherwise your array of results will be considered immutable inside the callback (i.e. all changes discarded).
Convert multidimensional array to single array using iterator_to_array
REF: http://php.net/manual/en/function.iterator-to-array.php
$service_desc= iterator_to_array(new RecursiveIteratorIterator(new RecursiveArrayIterator($your_array)), 0);
print_r($service_desc);
Result:
Array
(
[name] => Avaya Implementation Services
[service_id] => 14
[ser_type_id] => 1
[service_desc] =>Avaya Implementation Servic
)
I have an array as below, which has multiple columns. I want to search in the first column for a specific value, and have the rows that match returned. Is that possible to do?
For example:
Array (
[0] => Array ( [id] => 1 [column2] => value2 [column3] => value3 [column4] => value4 [column5] => value5 )
[1] => Array ( [id] => 1 [column2] => value2 [column3] => value3 [column4] => value4 [column5] => value5 )
[2] => Array ( [id] => 2 [column2] => value2 [column3] => value3 [column4] => value4 [column5] => value5
)
So let's say I want to search the "id" column for "1" and have the results displayed. How can this be done? Thank you so much!
If you are using PHP >= 5.5, then you can use the new array_column(), in conjunction with array_keys() and array_map().
Given your array, $array:
$keys = array_keys(array_column($array, 'id'), 1);
$new_array = array_map(function($k) use ($array){return $array[$k];}, $keys);
See demo
Since you have an nested Array you need two iterations:
$filtered = array();
$rows = Your Array;
foreach($rows as $index => $columns) {
foreach($columns as $key => $value) {
if ($key == 'id' && $value == '1') {
$filtered[] = $columns;
}
}
}
This should do the job.
I found a much simpler solution that I think is worthwhile sharing with the world
in_array(1, array_column($yourArray, 'id'));
Tested on PHP >= 5.5
These steps will always return a row in an array that uses a unique id column (in this example in the first column, 0)
1) Get an array of just IDs
$ids = array_column($my_table, 0);
2) Find the row with my ID
$row_index = array_search($id, $ids); (where $id is a certain ID)
3) Then I could use
$my_table[$row_index][n] (where n is a given column)
Use this function :
global $result;
function array_searc_result($array,$key,$value)
{
global $result;
foreach($array as $k=>$v)
{
if(array_key_exists($key,$v) && ($v[$key] == $value))
{
$result[] = $v;
}
}
return $result;;
}
$data = array_searc_result($array,'id',2);
echo '<pre>';
print_r($data);
echo '</pre>';
$array is your given array variable.
I use this helper to find matches by key / value:
function array_search_by_key($array, $key, $value) {
if(!is_array($array)) {
return [];
}
$results = [];
foreach($array as $element) {
if(isset($element[$key]) && $element[$key] == $value) {
$results[] = $element;
}
}
return $results;
}
I have this array:
Array
(
[count] => 12
[6] => CN=G_Information_Services,CN=Users,DC=hccc,DC=campus
[7] => CN=WEBadmin,CN=Users,DC=hccc,DC=campus
[9] => CN=G_ISDept,CN=Users,DC=hccc,DC=campus
[10] => CN=STAFF,CN=Users,DC=hccc,DC=campus
)
and I want to create an array of values that consist of the value between the first CN= and , of each array value below.
I probably will have to loop thru the array above, do a regex search for the first occurrence of cn and the value that follows it
I am not sure what I am doing wrong.
I need the final result to be an array that resembles this:
array('G_Information_Services', 'WEBadmin', 'G_ISDept', 'STAFF');
Use preg_match on each of the array values to get only the first corresponding CN value.
$found = array();
foreach ($arr AS $values) {
if (preg_match('/CN=([^,]+),/',$values,$matches))
$found[] = $matches[1];
}
Output
Array
(
[0] => G_Information_Services
[1] => WEBadmin
[2] => G_ISDept
[3] => STAFF
)
Try this (not the most efficient way but it should work):
foreach ($array as $key => $value)
{
if (is_numeric($key))
{
$array[$key] = explode(',', $array[$key]);
$array[$key] = $array[$key][0];
$array[$key] = substr($array[$key], 3);
}
}
This gets the first value of CN= of each element of the array, it also ignores any DC= values.
$arr = array(
'count' => 12,
6 => 'CN=G_Information_Services,CN=Users,DC=hccc,DC=campus',
7 => 'CN=WEBadmin,CN=Users,DC=hccc,DC=campus',
9 => 'CN=G_ISDept,CN=Users,DC=hccc,DC=campus',
10 => 'CN=STAFF,CN=Users,DC=hccc,DC=campus'
);
$newArr = array();
foreach($arr as $key => $value)
{
if($key != 'count')
{
$temp = explode(',', $value);
foreach($temp as $item)
{
if(strpos($item, 'CN=') === 0)
{
$item = substr($item, 3 );
$newArr[] = $item;
break 1;
}
}
}
}
print_r($newArr);
This question already has answers here:
How to Flatten a Multidimensional Array?
(31 answers)
Closed 5 months ago.
Is there any fast way to flatten an array and select subkeys ('key'&'value' in this case) without running a foreach loop, or is the foreach always the fastest way?
Array
(
[0] => Array
(
[key] => string
[value] => a simple string
[cas] => 0
)
[1] => Array
(
[key] => int
[value] => 99
[cas] => 0
)
[2] => Array
(
[key] => array
[value] => Array
(
[0] => 11
[1] => 12
)
[cas] => 0
)
)
To:
Array
(
[int] => 99
[string] => a simple string
[array] => Array
(
[0] => 11
[1] => 12
)
)
Give this a shot:
$ret = array();
while ($el = each($array)) {
$ret[$el['value']['key']] = $el['value']['value'];
}
call_user_func_array("array_merge", $subarrays) can be used to "flatten" nested arrays.
What you want is something entirely different. You could use array_walk() with a callback instead to extract the data into the desired format. But no, the foreach loop is still faster. There's no array_* method to achieve your structure otherwise.
Hopefully it will help someone else, but here is a function I use to flatten arrays and make nested elements more accessible.
Usage and description here:
https://totaldev.com/flatten-multidimensional-arrays-php/
The function:
// Flatten an array of data with full-path string keys
function flat($array, $separator = '|', $prefix = '', $flattenNumericKeys = false) {
$result = [];
foreach($array as $key => $value) {
$new_key = $prefix . (empty($prefix) ? '' : $separator) . $key;
// Make sure value isn't empty
if(is_array($value)) {
if(empty($value)) $value = null;
else if(count($value) == 1 && isset($value[0]) && is_string($value[0]) && empty(trim($value[0]))) $value = null;
}
$hasStringKeys = is_array($value) && count(array_filter(array_keys($value), 'is_string')) > 0;
if(is_array($value) && ($hasStringKeys || $flattenNumericKeys)) $result = array_merge($result, flat($value, $separator, $new_key, $flattenNumericKeys));
else $result[$new_key] = $value;
}
return $result;
}
This should properly combine arrays with integer keys. If the keys are contiguous and start at zero, they will be dropped. If an integer key doesn't yet exist in the flat array, it will be kept as-is; this should mostly preserve non-contiguous arrays.
function array_flatten(/* ... */)
{
$flat = array();
array_walk_recursive(func_get_args(), function($value, $key)
{
if (array_key_exists($key, $flat))
{
if (is_int($key))
{
$flat[] = $value;
}
}
else
{
$flat[$key] = $value;
}
});
return $flat;
}
You could use !isset($key) or empty($key) instead to favor useful values.
Here's a more concise version:
function array_flatten(/* ... */)
{
$flat = array();
array_walk_recursive(func_get_args(), function($value, $key) use (&$flat)
{
$flat = array_merge($flat, array($key => $value));
});
return $flat;
}