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
)
Related
Say for example I have the following array:
$h = array (
"app" => array (
"level1" => array (
"level2" => array (
"level3" =>3
),
"level4" => array (
"level5" => 2
)
)
)
);
What I wish to do is to create a string for every single sub-array found in here. For example, using the array above, the output would be:
Array
(
[0] => Array
(
[app.level1.level2.level3] => 3
)
[1] => Array
(
[app.level1.level4.level5] => 2
)
)
As you can see, each sub-array is concatenated with a '.' to represent the fact there is a child array with a value assigned given by the last node. Of course the only thing I can think of is to create a recursive function that could handle this, though this is where I'm having some trouble here. Here's what I started working on:
public static function buildString($array, $string ="") {
foreach($array as $h => $k) {
if(is_array($k)) {
$string .= $h.".";
return self::buildString($k, $string);
} else {
$string .= $h;
$j[] = array (
$string => $k
);
return $j;
}
}
}
Inputting the array given above within this method, I successfully get the first iteration:
Array
(
[0] => Array
(
[app.level1.level2.level3] => 3
)
)
And this is where I am at the moment and cannot seem to figure out how to do the rest of the array, or any size array for that matter.
Any hints//remarks would be appreciated.
You cannot return inside the foreach loop, you need to aggregate all of the recursive/non-recursive results and bubble them up. Something like this:
public static function buildString($array, $string ="") {
$j = array();
foreach($array as $h => $k) {
if(is_array($k)) {
$string .= $h.".";
$j = array_merge($j, self::buildString($k, $string));
} else {
$string .= $h;
$j[] = array (
$string => $k
);
}
}
return $j;
}
you can use array_walk() as a method:
$h = array (
"app" => array (
"level1" => array (
"level2" => array (
"level3" =>3
),
"level4" => array (
"level5" => 2
)
)
)
);
$results = array();
function get_strings($item, $key, $old_key = null) {
global $results;
if(is_array($item)) {
array_walk($item, 'get_strings', $old_key . $key . ".");
} else {
$results[$old_key . $key] = $item;
}
}
array_walk($h, 'get_strings');
print_r($results); //returns Array ( [app.level1.level2.level3] => 3 [app.level1.level4.level5] => 2 )
array_walk() documentation: http://php.net/manual/en/function.array-walk.php
Although I must give credit to #kennypu, I've made some slight modifications to the answer in order to contain the code in one function without the use of global or any other variables within the class (keeping it all in one method).
public static function buildString($array, $delimeter = '.') {
$results = array();
$func = function($item, $key, $old_key = NULL) use (&$func, &$results, $delimeter) {
if(is_array($item)) {
array_walk($item, $func, $old_key . $key . $delimeter);
} else {
$results[$old_key . $key] = $item;
}
};
array_walk($array, $func);
return $results;
}
In essence I created an anonymous function that uses parameters from the parent with the use of the key word use. Although not much documentation can be found for use some examples are shown here: Anonymous Functions.
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;
}
So I have this array.
Array
(
[0] => Array
(
[key_1] => something
[type] => first_type
)
[1] => Array
(
[key_1] => something_else
[type] => first_type
)
[2] => Array
(
[key_1] => something_else_3
[type] => second_type
)
[3] => Array
(
[key_1] => something_else_4
[type] => second_type
)
)
I have to sort by type value in a pattern like this:
first_type
second_type
first_type
second_type
My questions is, how can I do this?
Thanks a lot!
You need to use usort with a custom comparison function that compares the key_1 sub-keys of each item (you can use strcmp to do this conveniently). Assuming you do not want to change the structure of the resulting array, it would look something like this:
$arr = /* your array */
usort($arr, function($a, $b) { return strcmp($a['key_1'], $b['key_1']); });
So here's how I got it to work:
function filter_by_value($array, $index, $value) {
if(is_array($array) && count($array) > 0) {
foreach(array_keys($array) as $key){
$temp[$key] = $array[$key][$index];
if ($temp[$key] == $value){
$newarray[$key] = $array[$key];
}
}
}
return $newarray;
}
$array = /* array here */
$type1 = array_values(filter_by_value($array, 'type', '1'));
$type2 = array_values(filter_by_value($array, 'type', '2'));
$i = 1; $x = 1; $y = 1;
$sorted = array();
foreach ($array as $a) {
if ($i % 2) {
$sorted[$i-1] = $type1[$x-1];
$x++;
} else {
$sorted[$i-1] = $type2[$y-1];
$y++;
}
$i++;
}
Found filter_by_value() on php.net but I don't remember where so, that's not made by me.
Maybe this is not the best solution but it works pretty fine.
If sort() and its relevant alternatives don't work you will have to use usort() or uasort() with a custom function to sort this array.
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;
}
Basically my app is interacting with a web service that sends back a weird multidimensional array such as:
Array
(
[0] => Array
(
[Price] => 1
)
[1] => Array
(
[Size] => 7
)
[2] => Array
(
[Type] => 2
)
)
That's not a problem, but the problem is that the service keeps changing the index of those items, so in the next array the Price could be at 1 instead of 0.
How do I effeciently transform arrays like this into a single dimension array so I can access the variables through $var['Size'] instead of $var[1]['Size']?
Appreciate your help
$result = call_user_func_array('array_merge', $array);
Like this:
$result = array();
foreach($array as $inner) {
$result[key($inner)] = current($inner);
}
The $result array would now look like this:
Array
(
[Price] => 1
[Size] => 7
[Type] => 2
)
I am using laravel's helper: http://laravel.com/api/source-function-array_flatten.html#179-192
function array_flatten($array)
{
$return = array();
array_walk_recursive($array, function($x) use (&$return) { $return[] = $x; });
return $return;
}
function flattenArray($input, $maxdepth = NULL, $depth = 0)
{
if(!is_array($input)){
return $input;
}
$depth++;
$array = array();
foreach($input as $key=>$value){
if(($depth <= $maxdepth or is_null($maxdepth)) && is_array($value)){
$array = array_merge($array, flattenArray($value, $maxdepth, $depth));
} else {
array_push($array, $value);
// or $array[$key] = $value;
}
}
return $array;
}
Consider $mArray as multidimensional array and $sArray as single dimensional array this code will ignore the parent array
function flatten_array($mArray) {
$sArray = array();
foreach ($mArray as $row) {
if ( !(is_array($row)) ) {
if($sArray[] = $row){
}
} else {
$sArray = array_merge($sArray,flatten_array($row));
}
}
return $sArray;
}
I think i found best solution to this : array_walk_recursive($yourOLDmultidimarray, function ($item, $key) {
//echo "$key holds $item\n";
$yourNEWarray[]=$item;
});
If you use php >= 5.6, you may use array unpacking (it's much faster):
$result = array_merge(...$array);
See wiki.php.net on unpacking