Displaying an array inside an array? - php

I have an array inside an array and I'd like to simply print out the contents of it... the problem is what I'm trying doesn't work... ie
foreach($retval as $k=>$v){
if (is_array($v)){
foreach($v as $l=>$w){
echo $l . ' = ' . $w . '<br />';
}
} else {
echo $k . ' = ' . $v . '<br />';
}
Doing that however I end up with:
id = 2
name = Speakers
form_field = hidden
display_order = 0
groups = Array
So I'm not getting a foreach in that inside array.. what am I doing wrong? It seems actually that my code believes everything return is an array when I'm pretty sure that only 'groups' is an array.
the structure of the array looks like so:
array ( 0 => array ( 'id' => 2, 'name' => 'Speakers', 'form_field' => 'hidden', 'display_order' => '0', 'groups' => array ( 0 => array ( 'bit' => '1', 'name' => 'don', 'display_order' => '4', 'subscribers' => 8, ), 1 => array ( 'bit' => '2', 'name' => 'tyler', 'display_order' => '5', 'subscribers' => 0, ), 2 => array ( 'bit' => '4', 'name' => 'stephen', 'display_order' => '6', 'subscribers' => 0, ), 3 => array ( 'bit' => '8', 'name' => 'daniel', 'display_order' => '7', 'subscribers' => 0, ), 4 => array ( 'bit' => '16', 'name' => 'william', 'display_order' => '8', 'subscribers' => 0, ), 5 => array ( 'bit' => '32', 'name' => 'bobbys', 'display_order' => '9', 'subscribers' => 0, ), ), ), )
Long story short, I'm actually just trying to search this whole thing for say the name 'bobby' and get a simple true or false on whether that value exists anywhere in there.

print_r($myArray);
PHP Manual
<?php
$a = array ('a' => 'apple', 'b' => 'banana', 'c' => array ('x', 'y', 'z'));
print_r ($a);
?>
would give:
Array
(
[a] => apple
[b] => banana
[c] => Array
(
[0] => x
[1] => y
[2] => z
)
)
Not sure if this is what you are looking for...
print_r() gives you a visual representation while var_export() returns valid, executable php code. Manual: var_export()

You're assuming that arrays are only doubly-nested, when $retval[<something>]['groups'] is also an array. Use recursion to handle this instead of just adding levels upon levels.

It sounds like you need to reconsider what you are trying to do.
If you just want to see what is in your array so that you know how to get at a particular piece of data, then you're probabaly after print_r, var_export or similar as mentioned above.
print_r($retval);
If you want your php script to be able to work out on it's own whether 'bobby' is in the array, then you might have some more information that will help your search. For example, do you know the structure of your array and that you're searching for a name? If so, then you only need to check the strings that are in $array[$foo]['name']. You could adapt your code like so:
foreach($retval as $k=>$v) {
if ($v['name'] == 'bobby') {
echo "Bobby is at index $k";
}
}
PHP contains lots of functions for arrays, although these tend to be for single-dimension arrays.
P.S. Please edit the structure of your array to make it easier to read.

If your goal is to understand if a value is in any nested array you can do this:
foreach($retval as $vec){
if(in_array("bobby", $vec)
do something

Use a RecursiveArrayIterator wrapped in RecursiveIteratorIterator. The syntax will then be:
$arr = array('this is your complicated multi-dimensional array');
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr));
foreach($iterator as $key => $value){
echo '['.$key.'] => '.$value.'<br />';
}
You can even use $iterator->depth() to determine the depth of a current element.

Related

Prune/reduce a multi-dimensional array in PHP to a certain depth

I've searched for this on and off for a couple of years to no avail. Occasionally I'd like to prune a multi-dimension to a certain depth. This would be useful when storing large recursive data sets when you only need data to a certain depth and the rest should be discarded.
For example, given the following array:
$arr = array(
'1' => array(
'1.1' => '1.1.1'),
'2',
'3' => array(
'3.1' => array(
'3.1.1' => '3.1.1.1')
)
);
I would want to prune it back to x number of dimensions calling something like this:
some_prune_method($arr array, $dimensions integer)
...and expect data to be returned something like this:
print_r(some_prune_method($arr, 1));
Array(
[
'1',
'2',
'3'
]
)
print_r(some_prune_method($arr, 2));
Array(
[
'1' => ['1.1'],
'2',
'3' => ['3.1']
]
)
print_r(some_prune_method($arr, 3));
Array(
[
'1' => ['1.1'],
'2',
'3' => ['3.1' => '3.1.1']
]
)
I can think how to do this manually using a callback to iterate through the array but that's slow. Ideally this would need to be done WITHOUT iterating through the entire array.
Maybe I'm missing a simple way to do this?
Think this is what your after. The main concept is just a recursive method to copy the input array which keeps track of the depth. Each time it goes back round it takes 1 off the depth and just before checking if it needs to call the recursive loop it checks if the depth will allow it. If not then it just adds the key to the output loop instead.
$arr = array(
'1' => array(
'1.1' => '1.1.1'),
'2',
'3' => array(
'3.1' => array(
'3.1.1' => '3.1.1.1')
)
);
function some_prune_method ( $array, $depth ) {
$output = [];
foreach ( $array as $key => $element ) {
if ( is_array($element)) {
if ( $depth > 1 ) {
$output [$key] = some_prune_method ( $element, $depth-1 );
}
else {
$output[] = $key;
}
}
else {
$output[] = $element;
}
}
return $output;
}
print_r(some_prune_method($arr, 2));
gives...
Array
(
[1] => Array
(
[0] => 1.1.1
)
[2] => 2
[3] => Array
(
[0] => 3.1
)
)

Undefined offset Error when searching Array

I am searching an array for a known value wid to get the key which will then help me get the cid value.
$proximity = array(
'0' => array ('wid' => 4, 'cid' => 100),
'1' => array ('wid' => 1, 'cid' => 50),
'3' => array ('wid' => 2, 'cid' => 50)
);
$key = array_search(2, array_column($proximity, 'wid'));
print_r($key);
print_r($proximity[$key]['cid']);
When I search for wid 4 and 1 everything works great.
However when I search for wid: 2 I get Undefined offset: 2.
Why is this happening and how do I fix it?
Array_column returns values of field as usual indexed array, even if source array is associative. So the returned key is correct only when source array has no omitted indexes, and your search, in fact, gets "position" in array.
For example, for such an array
$proximity = array(
'a' => array ('wid' => 4, 'cid' => 100),
'b' => array ('wid' => 1, 'cid' => 50),
'c' => array ('wid' => 2, 'cid' => 50)
);
array_column will return
Array
(
[0] => 4
[1] => 1
[2] => 2
)
If you really want to search through array_column, to work around this problem and get item by that "position", use
print_r(array_slice($proximity, $key, 1)['cid']);
or
print_r(array_values($proximity)[$key]['cid']);
It's because when you are doing array_search() it is only searching the first level of the array, you can search like the following:
<?php
echo 'hello world';
$proximity = array(
'0' => array ('wid' => 4, 'cid' => 100),
'1' => array ('wid' => 1, 'cid' => 50),
'3' => array ('wid' => 2, 'cid' => 50)
);
foreach($proximity as $subarray){
$key = array_search(2, array_column($subarray, 'wid'));
echo print_r($key) . '<br />';
echo print_r($proximity[$key]['cid']) . '<br />';
}
?>
This searches each sub array that is in the main array, meaning it doesn't matter how many elements are in $proximity, it will search all of them.
array_column() is trashing your original keys. I don't think there is any shame in using a loop with a break. This is clean and fast and the gaps in the keys are no bother; in fact your original keys are preserved if you need them.
Code: (demo: https://3v4l.org/8XWcf )
$proximity = array(
'0' => array ('wid' => 4, 'cid' => 100),
'1' => array ('wid' => 1, 'cid' => 50),
'3' => array ('wid' => 2, 'cid' => 50)
);
$wid=2;
foreach($proximity as $i=>$a){
if($a['wid']==$wid){
echo "i=$i and cid={$a['cid']}";
break;
}
}
Output:
i=3 and cid=50
If you don't want control structures as iterators, this seems like a sensible alternative:
$wid=2;
$proximity=array_column($proximity,NULL,'wid');
if(isset($proximity[$wid])){
echo "cid={$proximity[$wid]['cid']}";
}else{
echo 'wid not found';
}
This assumes wid values are unique and uses the values as keys for the subarrays. Demo : https://3v4l.org/Ph1tH

PHP arrays be outputed to JSON format

PHP arrays
$grades = array( array( name => "tom",
grade => 'A'
),
array( name => "jeff",
grade=> 'B'
),
array( name => "lisa",
grade => 'C'
)
);
$output=array
( 'status'=>'ok',
'content'=>$grades
)
And the final JSON output I want to see would be {"status":'ok',"content":"{"tom":"A","jeff":"B","lisa":"B"}"}
The question is how should I manipulated the array so it can give me the final output like above JSON?
would json_encode($output); echo $output do the trick?
or
Do I have to do
json_encode($grades) then another json_encodes($output) but I am seeing extra \ thing like {"status":1,"content":"{\"tom\":\"A\",\"jeff\":\"B\",\"lisa\":\"B\"}"}
Try this simple command
$my_array = [
"test" => "value",
"another" => [
"fruits" => ["Apple", "Orange"]
]
];
print_r(json_encode($my_array));
It will produce
{
"test":"value",
"another":{
"fruits":["Apple","Orange"]
}
}
I don't understand why you don't write just this:
<?php
$grades = array(
array(
'name' => 'tom',
'grade' => 'A'
),
array(
'name' => 'jeff',
'grade' => 'B'
),
array(
'name' => 'lisa',
'grade' => 'C'
),
);
$output = array(
'status' => 'ok',
'content' => $grades,
);
print_r(json_decode(json_encode($output)));
It prints:
stdClass Object
(
[status] => ok
[content] => Array
(
[0] => stdClass Object
(
[name] => tom
[grade] => A
)
[1] => stdClass Object
(
[name] => jeff
[grade] => B
)
[2] => stdClass Object
(
[name] => lisa
[grade] => C
)
)
)
Isn't is the expected result?
Don't call json_encode($grades) before json_encode($output), unless you have some unmentioned reason to want the grades as a string literal instead of json object. json_encode() will recursively encode all child arrays inside $output, there's no need to encode them separately.
As you may have figured out, an array's associative keys get represented as keys in the resulting JSON object, e.g. {key1: value1, ...}, as clearly demonstrated from the output you got.
Secondly, an array containing other arrays will be represented as a list in JSON, e.g. [...]
I believe your earlier code should looked something like this:
$grades = array(
array('name' => 'tom', 'grade' => 'A'),
array('name' => 'jeff', 'grade' => 'B'),
array('name' => 'lise', 'grade' => 'C'),
);
$output = array(
'status' => 'ok',
'content' => $grades
);
echo json_encode($output);
So applying the rules I have outlined above will result in the JSON below.
{"status":"ok","content":[{"name":"tom","grade":"A"},{"name":"jeff","grade":"B"},{"name":"lise","grade":"C"}]}
I personally think you should use this since it is a better representation than the one you desire to have. However, the codes below should give you your results.
$grades = array(
'tom' => 'A',
'jeff' => 'B',
'lisa' => 'B',
);
$output = array(
'status' => 'ok',
'content' => $grades
);
echo json_encode($output);
Output:
{"status":"ok","content":{"tom":"A","jeff":"B","lisa":"B"}}
The reason you are getting the 'extra' \ is that what you say you want as output is not valid JSON. PHP's default function has it right, yours will not parse in a JSON parser.
If you really want almost-json, you'll have to roll your own.
you have to change the format of $grade array to get the desired output . try below
$grade_format= array();
foreach($grades as $k=>$v)
{
//array_push($output,$k);
$grade_format[$v['name']]=$v['grade'];
}
//echo "<pre>";
//print_r($grade_format);
$output=array
( 'status'=>'ok',
'content'=>$grade_format
);
echo "<pre>";
echo json_encode($output,JSON_FORCE_OBJECT);
//output would be
{"status":"ok","content":{"tom":"A","jeff":"B","lisa":"C"}}
is that you want??
REFERENCE

Is there a PHP Array Group By function?

$arr1 = array('a' => '1', 'b' => 'blah', 'c' => 'whatever...',
'aa' => '2', 'bb' => 'lbha', 'cc' => 'everwhat...', 'dd' => 'bingo',
'aaa' => '3', 'bbb' => 'halb', 'ccc' => 'revetahw...');
In the array I have three different index lengths a,b and c are all 1 in length. aa,bb,cc and dd are all 2 in length. And aaa,bbb and ccc are all 3 in length.
What I'm trying to do is find the index (group by length) with the most elements and the greatest length.
so I would use aa,bb,cc,dd as they have 4 elements, this would return the index length of 2.
I want to know how I can get the 2?
Here is what I'm trying but it's not working
foreach($arr1 as $key => $data) {
$index_length_arr[strlen($key)] = $index_length_arr[$key] + 1;
}
Results:
Array
(
[1] => 1
[2] => 1
[3] => 1
)
Expected Output:
Array
(
[1] => 3
[2] => 4
[3] => 3
)
Then I could see that index (with the length of 2) had the most elements:
'aa' => '2', 'bb' => 'lbha', 'cc' => 'everwhat...', 'dd' => 'bingo',
$array = array_count_values(array_map('strlen',array_keys($arr1)));
Should give ya what ya want.
Edit:
Your original code was fine except you have to change the = .... to $index_length_arr[strlen($key)]
You were using two different keys.
I'd recommend creating your own (or using a library that already does it). It'd be something like this (did not test it):
function groupBy($array, $function)
{
$dictionary = [];
if ($array) {
foreach ($array as $item) {
$dictionary[$function($item)][] = $item;
}
}
return $dictionary;
}
Using it like this:
$usersByAge = groupBy($users, function ($age) { return $user->age; } );
I would highly recommend using lstrojny's functional-php https://github.com/lstrojny/functional-php which includes a group() function along with a host of other useful functional programming concepts.
$arr1 = array('a' => '1', 'b' => 'blah', 'c' => 'whatever...',
'aa' => '2', 'bb' => 'lbha', 'cc' => 'everwhat...', 'dd' => 'bingo',
'aaa' => '3', 'bbb' => 'halb', 'ccc' => 'revetahw...');
$tmpArray = array();
foreach ($arr1 AS $key => $val) {
if (empty($tmpArray)) {
$tmpArray[strlen($key)] = 0;
}
$tmpArray[strlen($key)]++;
}
print_r($tmpArray);
Gets you your expected result.

Find all second level keys in multi-dimensional array in php

I want to generate a list of the second level of keys used. Each record does not contain all of the same keys. But I need to know what all of the keys are. array_keys() doesn't work, it only returns a list of numbers.
Essentially the output Im looking for is:
action, id, validate, Base, Ebase, Ftype, Qty, Type, Label, Unit
I have a large multi-dimensional array that follows the format:
Array
(
[0] => Array
(
[action] => A
[id] => 1
[validate] => yes
[Base] => Array
(
[id] => 2945
)
[EBase] => Array
(
[id] => 398
)
[Qty] => 1
[Type] => Array
(
[id] => 12027
)
[Label] => asfhjaflksdkfhalsdfasdfasdf
[Unit] => asdfas
)
[1] => Array
(
[action] => A
[id] => 2
[validate] => yes
[Base] => Array
(
[id] => 1986
)
[FType] => Array
(
[id] => 6
)
[Qty] => 1
[Type] => Array
(
[id] => 13835
)
[Label] => asdssdasasdf
[Unit] => asdger
)
)
Thanks for the help!
<?php
// Gets a list of all the 2nd-level keys in the array
function getL2Keys($array)
{
$result = array();
foreach($array as $sub) {
$result = array_merge($result, $sub);
}
return array_keys($result);
}
?>
edit: removed superfluous array_reverse() function
array_keys(call_user_func_array('array_merge', $a));
Merge all values and retrieve the resulting keys.
One liner:
$keys=array_unique(array_reduce(array_map('array_keys',$data),'array_merge',[]));
Or in a function:
function get_array_children_keys($data) {
return array_unique(
array_reduce(array_map('array_keys', $data), 'array_merge', [])
);
}
Now lets break this down with an example, here is some sample data:
[
['key1' => 0],
['key1' => 0, 'key2' => 0],
['key3' => 0]
]
Starting with the inner most function, we run array_map with the array_keys function:
array_map('array_keys', $data)
This gives us the keys of from all child arrays
[
['key1'],
['key1', 'key2'],
['key3']
]
Then we run the array_reduce on the data with the array_merge callback and an empty array as the initial value:
array_reduce(..., 'array_merge', []);
This converts our multiple arrays into 1 flat array:
[
'key1',
'key1',
'key2',
'key3'
]
Now we strip out our duplicates with array_unique:
array_unique(...)
And end up with all our keys:
[
'key1',
'key2',
'key3'
]
foreach($bigArray as $array){
foreach($array as $key=>$value){
echo $key;
}
}
That should do what you want.
What about something like this :
$your_keys = array_keys($your_array[0]);
Of course, this is considering all sub-arrays have the same keys ; in this case, you only need the keys of the first sub-array (no need to iterate over all first-level sub-arrays, I guess)
And, as a shortened / simplified example :
$your_array = array(
array(
'action' => 'A',
'id' => 1,
'base' => array('id' => 145),
),
array(
'action' => 'B',
'id' => 2,
'base' => array('id' => 145),
),
array(
'action' => 'C',
'id' => 3,
'base' => array('id' => 145),
)
);
$your_keys = array_keys($your_array[0]);
var_dump($your_keys);
Will get you :
array
0 => string 'action' (length=6)
1 => string 'id' (length=2)
2 => string 'base' (length=4)
You can the use implode to get the string you asked for :
echo implode(', ', $your_keys);
will get you :
action, id, base
ie, the list of the keys of the first sub-array.
function __getAll2Keys($array_val){
$result = array();
$firstKeys = array_keys($array_val);
for($i=0;$i<count($firstKeys);$i++){
$key = $firstKeys[$i];
$result = array_merge($result,array_keys($array_val[$key]));
}
return $result;
}
try this function. It will return as you want.
While #raise answers provides a shortcut, it fails with numeric keys. The following should resolve this:
$secondKeys=array_unique(call_user_func_array('array_merge', array_map('array_keys',$a)));
array_map('array_keys',$a) : Loop through while getting the keys
...'array_merge'... : Merge the keys array
array_unique(... : (optional) Get unique keys.
I hope it helps someone.
UPDATE:
Alternatively you can use
$secondKeys=array_unique(array_merge(...array_map('array_keys', $a)));
That provides same answer as above, and much faster.
My proposal, similar to this answer but faster and using spread operator (PHP 5.6+).
array_merge(...array_values($fields))
if you want move names to array values and reset keys to 0..n just use array_keys in last step.
array_keys(array_merge(...array_values($fields)))
Maybe you can use array_map function, which allows you to avoid array iteration and return an array with the keys you need as values.
will be like this
$newArray = array_map(function($value){return array_keys($value);},$yourArray);
var_dump($newArray);
array (size=2)
0 =>
array (size=9)
0 => string 'action' (length=6)
1 => string 'id' (length=2)
2 => string 'validate' (length=8)
3 => string 'Base' (length=4)
4 => string 'EBase' (length=5)
5 => string 'Qty' (length=3)
6 => string 'Type' (length=4)
7 => string 'Label' (length=5)
8 => string 'Unit' (length=4)
1 =>
array (size=9)
0 => string 'action' (length=6)
1 => string 'id' (length=2)
2 => string 'validate' (length=8)
3 => string 'Base' (length=4)
4 => string 'FType' (length=5)
5 => string 'Qty' (length=3)
6 => string 'Type' (length=4)
7 => string 'Label' (length=5)
8 => string 'Unit' (length=4)
With this function you can get all keys from a multidimensional array
function arrayKeys($array, &$keys = array()) {
foreach ($array as $key => $value) {
$keys[] = $key;
if (is_array($value)) {
$this->arrayKeys($value, $keys);
}
}
return $keys;
}
Only if all records have the same keys you could do:
$firstItem = reset($array);
$keys = array_keys($firstItem);
Obviously, this is not the correct answer to this specific question, where the records have different keys. But this might be the question you find when looking how to retrieve second level keys from an array where all keys are the same (I did). If all the record have the same keys, you can simply use the first item in the array with reset() and get the keys from the first item with array_keys().

Categories