php: How to foreach a multidimensional array? - php

I have been trying for a while but I can't seem to loop through a multi dimensional array.
I have this array:
$Work["work_time"] = array();
$Work["break_time"] = array();
$Work["meeting_time"] = array();
$Work["login_time"] = array();
$Work["logout_time"] = array();
$Work["work_date"] = array();
Which print_r($Work) outputs this
Array
(
[work_time] => Array
(
[0] => 0.00
[1] => 3.96
[2] => 7.75
)
[break_time] => Array
(
[0] => 0.00
[1] => 0.00
[2] => 1.06
)
[meeting_time] => Array
(
[0] => 0.00
[1] => 0.00
[2] => 0.00
)
[login_time] => Array
(
[0] => 10:11
[1] => 08:48
[2] => 09:09
)
[logout_time] => Array
(
[0] => 00:00
[1] => 13:00
[2] => 17:59
)
[work_date] => Array
(
[0] => 2018-04-13
[1] => 2018-04-16
[2] => 2018-04-17
)
)
And then I tried to use a foreach loop to loop through it and get the values but it returns nothing..
foreach ($Work as $row) {
echo $row["login_time"];
}
What am I missing?

The array you're trying to iterate with your foreach loop is not the same as the array you have. In order to use that loop, your array would need to be like this instead:
[
[
'work_time' => 0.00,
'break_time' => 0.00,
'meeting_time' => 0.00,
'login_time' => '10:11',
'logout_time' => '00:00',
'work_date' => '2018-04-13'
],
[
'work_time' => 3.96,
'break_time' => 0.00,
'meeting_time' => 0.00,
'login_time' => '08:48',
'logout_time' => '13:00',
'work_date' => '2018-04-16'
],
[
'work_time' => 7.75,
'break_time' => 1.06,
'meeting_time' => 0.00,
'login_time' => '09:09',
'logout_time' => '17:59',
'work_date' => '2018-04-17'
],
];
The array you have looks like the type of input you get if you have an HTML form with multiple rows of inputs with names like this:
<input type="text" name="work[work_time][]">
If that is the case, you can get an array like the one I showed above instead by switching the keys around and specifying a numeric key for each row:
<input type="text" name="work[0][work_time]">
Then it will make more sense to access the data as rows. If that's not the case, well, never mind. :)
On the other hand, with the array you have, you can just iterate one of the inner arrays directly. For example, if you wanted to show login_time values, it's just
foreach ($Work['login_time'] as $login_time) {
echo $login_time;
}
If you need to get corresponding values from the other inner arrays, you can use the key from the array you're iterating to access those as well:
foreach ($Work['login_time'] as $key => $login_time) {
echo 'login time: ' . $login_time . ', work_date: ' . $Work['work_date'][$key];
}

If you really dont know how many dimensions you are dealing with, a recursive solution is what you need.
Here is my code:
$Work["work_time"] = array(1, 2, 3);
$Work["break_time"] = array(4, 5, 6);
$Work["meeting_time"] = array(7, 8, 9);
$Work["login_time"] = array(10, 11, 12);
$Work["logout_time"] = array(13, 14, 15);
$Work["work_date"] = array(16, 17, 18);
function forLoop($array){
foreach ($array as $row) {
if(is_array($row)){
forLoop($row);
}
else{
echo $row;
echo " ";
}
}
}
forLoop($Work);
Output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
You actually need to make a formating or something to make it work the way you want it to.
Edit: forLoop function calls it's self so it will work on any dimension array. Tell me what you think!

If you already know the key you need (login_time), you do not need to iterate the array. You can access it directly as $Work["login_time"].
If you want to iterate $Work["login_time"], you can use foreach:
foreach ($Work['login_time'] as $row) {
echo $row;
}

Probably need multiple for loops
foreach ($Work as $row) {
foreach($row as $key => $rs) {
echo $rs;
}
}

To loop completely you would need a 2nd foreach inside the first foreach. Like This:
foreach ($Work as $row) {
foreach ($row as $key => $value) {
echo "$key - $value";
}
}

foreach ($dataArray as $innerArray){
foreach ($innerArray as $key=>$value){
// here is where you access the array -- $value
}
}

Related

How to move values from 2nd array into the empty places of 1st array

How to move values from 2nd array into the empty places of 1st array
1st array as below
Array
(
[0] => 1
[1] =>
[2] => 4
[3] =>
)
2nd array as below
Array
(
[0] => 5
[1] => 9
)
I want output as merging 2nd array into 1st as shown below
Array
(
[0] => 1
[1] => 5
[2] => 4
[3] => 9
)
I have tried below code.....
for($i=0; $i<$count; $i++){
for($j=$i; $j<=$i; $j++)
if(empty($assign_taskk[$i])){
$assign_taskk[$i] = $taskkk[$i];
}
}
plz help me out for same
Lets say your arrays look like:
$a1 = [
0 => 1,
1 => null,
2 => 4,
3 => null,
];
$a2 = [
0 => null,
1 => 5,
2 => null,
3 => 9,
];
Then you can iterate over first array and add values from the second one when needed:
foreach ($a1 as $k => $v) {
if (empty($v) && !empty($a2[$k])) {
$a1[$k] = $a2[$k];
}
}
Another way to do it using below way-
<?php
$arr1= [1,null,4,null];
$arr2 = [null,5,null,9];
$result = array_values(array_filter($arr1) + array_filter($arr2));
print_r($result)
?>
DEMO: https://3v4l.org/R4aeE
Hi #amod try this
$_newArray = array_values(array_filter($array1) + array_filter($array2));
print_r($_newArray);
You can use below code for this:
$firstArray = [1,'',4,''];
$secondArray = [5,9];
$secondArrayCounter = 0;
foreach($firstArray as $key => $value) {
if (empty($value)) {
$firstArray[$key] = $secondArray[$secondArrayCounter];
$secondArrayCounter++;
}
}
print_r($firstArray);
Hope it helps you.

Combine two different dimensional arrays PHP

I have two different dimensional arrays.
Array 1:
Array1
(
[0] => Array
(
[id] => 123
[price] => 5
[purchase_time] => 2014/4/10
)
[1] => Array
(
[id] => 123
[price] => 5
[purchase_time] => 2014/5/17
)
)
Array 2:
Array2
(
[0] => 5
[1] => 8
)
I want something like this:
Array
(
[0] => Array
(
[id] => 123
[price] => 5
[purchase_time] => 2014/4/10
[Qty] => 5
)
[1] => Array
(
[id] => 123
[price] => 5
[purchase_time] => 2014/5/17
[Qty] => 8
)
)
Basically the first array is the information I got from a SQL table. The second array contains the quantity for the products sold. I now want to combine these two array together and use the combined array to create a new table. Since these two arrays have different dimensions. I'm not sure how to do it. Here is my try:
$i = 0;
foreach($array1 as $row)
{
$newarray = array_merge($row,$array2[$i]);
$i++;
}
Might be a simpler way, but for fun without foreach:
array_walk($array1, function(&$v, $k, $a){ $v['Qty'] = $a[$k]; }, $array2);
The simplest way is:
$i = 0;
foreach($array1 as &$row) {
$row['Qty'] = $array2[$i++];
}
Or if keys of both arrays are the same (0,1,2...) and array have the same length:
foreach($array1 as $k => &$row) {
$row['Qty'] = $array2[$k];
}
If the $array1 and $array2 are mapped by the same indexes, so they have same length, you can try:
foreach($array2 as $index=>$quantity){
$array1[$index]['Qty'] = $quantity;
}
And it´s done!
If you want to keep the original $array1 untouched, you can make a copy before the foreach.
Create new array and store it there. You can access the value of $array2 because they have the same index of $array1 so you can use the $key of these two arrays.
$array3 = [];
foreach($array1 as $key => $val) {
$array3[] = [
'id' => $val['id'],
'price' => $val['price'],
'purchase_time' => $val['purchase_time'],
'Qty' => $array2[$key]
];
}
print_r($array3);

How to return array as multi dimensional array?

I i'm developing php application. I have used Google Chart API for display charts.
I have select and returned necessary data for chart.
I got following array as my output.
print_r($output);
//Out put
Array
(
[0] => Array
(
[month] => April
[sec_id] => 2
[sec_name] => Commerce
[count] => 1
)
[1] => Array
(
[month] => June
[sec_id] => 2
[sec_name] => Commerce
[count] => 3
)
[2] => Array
(
[month] => July
[sec_id] => 2
[sec_name] => Commerce
[count] => 1
)
[3] => Array
(
[month] => August
[sec_id] => 4
[sec_name] => Science
[count] => 3
)
[4] => Array
(
[month] => August
[sec_id] => 3
[sec_name] => Maths
[count] => 2
)
[5] => Array
(
[month] => August
[sec_id] => 1
[sec_name] => Art
[count] => 2
)
[6] => Array
(
[month] => August
[sec_id] => 2
[sec_name] => Commerce
[count] => 2
)
)
print_r(json_encode($output)); // return above array as output
I request above data using ajax ( data type is JSON)
I want to return data as bellow to generate google chart.
[
['Month', 'Art', 'Commerce', 'Maths', 'Sience'],
['April', '', 2, '', ''],
['June', '', 3, '', ''],
['July', '', 1, '', ''],
['August', 2, 2, 3, 3]
]
I tried this this code
$output = array();
$output[0] = array('Month', 'Art', 'Commerce', 'Maths', 'Science');
foreach($records as $key=> $record){
$art =''; $commerce =''; $maths=''; $science='';
if($record['sec_id'] == 1){
$art = $record['count'];
}else if($record['sec_id'] == 2){
$commerce = $record['count'];
}else if($record['sec_id'] == 3){
$maths = $record['count'];
}else if($record['sec_id'] == 4){
$science = $record['count'];
}
$output[++$key] = array(0 => $record['month'], 1 => $art, 2 => $commerce, 3 => $maths, 4 => $science);
}
function super_unique($array){
$result = array_map("unserialize", array_unique(array_map("serialize", $array)));
foreach ($result as $key => $value){
if ( is_array($value)){
$result[$key] = super_unique($value);
}
}
return $result;
}
$output = super_unique($output);
Out put was
[["Month","Art","Commerce","Maths","Science"],["April","","1"],["June","","3"],["July","","1"],{"0":"August","1":"","4":"3"},{"0":"August","1":"","3":"2"},["August","2",""],["August","","2"]]
This is pretty straightforward to loop through and reorganize, particularly since your sec_ids match up nicely with the array indices.
Example:
$temp = array();
$output = array(
array('Month', 'Art', 'Commerce', 'Maths', 'Science')
);
foreach ($records as $record) {
$month = $record["month"];
$sec_id = $record["sec_id"];
$count = $record["count"];
if (!isset($temp[$month])) {
$temp[$month] = array_fill(0, 5, '');
}
$temp[$month][0] = $month;
$temp[$month][$sec_id] += $count;
}
$output = array_merge($output, array_values($temp));
echo json_encode($output);
Output:
[["Month","Art","Commerce","Maths","Science"],["April","",2,"",""],["June","",3,"",""],["July","",1,"",""],["August",2,2,2,3]]
Let's rethink your algorithm. As you go through each element in records, we need to ask two things: what data are we pulling out and what do we want to do with it?
The first question is simple: we're just pulling out the value 'count'.
The second question is going to determine our algorithm. What we want to do is take that 'count' value, and stick it a particular spot in our ourpur array.
Looking at the output array as a table, we can see that the desired position of 'count' is determined by the 'month' field (which determines the row) and by the 'sec_id'/'sec_name' fields (which determine the column). So what you want your loop to look like is this...
foreach($records as $record)
{
$output[$record['month']][$record['sec_id']] = $record['count']
}
The first caveat to this is that for each unique month, you do still need to create and initialize the sub-array, and you must do it only once. So, the loop becomes.
foreach($records as $record)
{
if(!is_array($output[$record['month']]))
$output[$record['month']] = array(0 => $record['month'], 1 => '', 2 => '', 3 => '', 4 => '');
$output[$record['month']][$record['sec_id']] = $record['count']
}
Finally, we used the actual month name as the keys in the top-level array. To comply with the numeric-only keys specified in your desired output, we can ditch those keys with the following piece of code.
$output = array_values($output)
If I'm right in thinking you were trying to use super_unique() to combine rows with the same month, that's not what it was doing at all. Firstly, array_unique() doesn't combine rows, it eliminates duplicates. Since you were comparing serialized rows, rather than just looking at the month field, none of your rows were duplicates, so that function was doing nothing. Furthermore, since several of your array fields were set to '', the serialize/unserialize process was actually causing those fields to get dropped, which is why you were ending up with sub-arrays of less than five elements, and with associative keys.

PHP grouping arrays within array by value

Hi I've got a bit of a problem and I can't seem to find the answer. I have an array with arrays in it and want to group these sub arrays into groups based on the same value for a field. This is my code and allows me to sort my arrays based on the arrays inside values. How do I group the result based on shared values? I probably won't know all the values as some are based on date and I want to for instance group all per day/month
if($filter == "ORDER BY TODO_REF DESC"){
$type_sort = 0;
};
if($filter == "ORDER BY TODO_PRIO DESC"){
$type_sort = 2;
};
if($filter == "ORDER BY TODO_DEAD DESC"){
$type_sort = 3;
};
function aasort (&$array, $key) {
$sorter=array();
$ret=array();
reset($array);
foreach ($array as $ii => $va) {
$sorter[$ii]=$va[$key];
}
asort($sorter);
foreach ($sorter as $ii => $va) {
$ret[$ii]=$array[$ii];
}
$array=$ret;
}
aasort($test_array, $type_sort);
print_r($test_array);
Current output:
priority
Array
(
[3] => Array
(
[0] => 2
[1] => sdfsdgdfgdfgdfg
[2] => 3
[3] => 2013-05-30 13:53:23
)
[2] => Array
(
[0] => 1
[1] => This must also be done
[2] => 4
[3] => 2013-03-28 12:13:34
)
[1] => Array
(
[0] => 1
[1] => testing this show me 2
[2] => 5
[3] => 2029-02-23 17:27:20
)
[0] => Array
(
[0] => 1
[1] => Do this task and make sure it gets done
[2] => 5
[3] => 2013-06-28 12:12:41
)
)
What I want would be something like this, where they are split into seperate arrays based on sub array key 2:
Array
(
[3] => Array
(
[0] => 2
[1] => sdfsdgdfgdfgdfg
[2] => 3
[3] => 2013-05-30 13:53:23
)
)
Array
(
[2] => Array
(
[0] => 1
[1] => This must also be done
[2] => 4
[3] => 2013-03-28 12:13:34
)
)
Array
(
[1] => Array
(
[0] => 1
[1] => testing this show me 2
[2] => 5
[3] => 2029-02-23 17:27:20
)
[0] => Array
(
[0] => 1
[1] => Do this task and make sure it gets done
[2] => 5
[3] => 2013-06-28 12:12:41
)
)
$array_1 = array();
$array_2 = array();
foreach($test_array as $item) {
if($item[0] == 1) {
$array_1[] = $item;
} elseif($item[0] == 2) {
$array_2[] = $item;
}
}
$final_array = array($array_1, $array_2);
There must be more optimized codes, but this should serve your needs.
array_multisort() is what you're after it will allow you to sort primary array by sub array and maintain the key value link
I use the below for sorting a rather hefty multi-dimensional array based off sort order arrows asc/desc on a table with many columns and sortable columns. Its abit of a mess but you should be able to follow it.
if (strlen($_GET['col'])<1) {
foreach ($dataarray as $key => $row) {
$spend[$key] = $row[6];
}
array_multisort($spend, SORT_DESC, $dataarray);
} else if ($_GET['col']=="spend"){
foreach ($dataarray as $key => $row) {
$spend[$key] = $row[3];
}
if ($_GET['order']=="asc") {
array_multisort($spend, SORT_ASC, $dataarray);
} else {
array_multisort($spend, SORT_DESC, $dataarray);
}
} else if ($_GET['col']=="name"){
foreach ($dataarray as $key => $row) {
$name[$key] = $row[1];
}
if ($_GET['order']=="asc") {
array_multisort($name, SORT_ASC, $dataarray);
} else {
array_multisort($name, SORT_DESC, $dataarray);
}
} else if ($_GET['col']=="avg"){
foreach ($dataarray as $key => $row) {
$avg[$key] = $row[4];
}
if ($_GET['order']=="asc") {
array_multisort($avg, SORT_ASC, $dataarray);
} else {
array_multisort($avg, SORT_DESC, $dataarray);
}
} else if ($_GET['col']=="sites"){
foreach ($dataarray as $key => $row) {
$sites[$key] = $row[5];
}
if ($_GET['order']=="asc") {
array_multisort($sites, SORT_ASC, $dataarray);
} else {
array_multisort($sites, SORT_DESC, $dataarray);
}
} else if ($_GET['col']=="rate"){
foreach ($dataarray as $key => $row) {
$rate[$key] = $row[6];
}
if ($_GET['order']=="asc") {
array_multisort($rate, SORT_ASC, $dataarray);
} else {
array_multisort($rate, SORT_DESC, $dataarray);
}
} else {
foreach ($dataarray as $key => $row) {
$spend[$key] = $row[2];
}
array_multisort($spend, SORT_DESC, $dataarray);
}
Rather than a block of if-elseif-elseif-elseif...else conditions to determine the sorting/grouping column, I always recommend a lookup array followed by a very quick isset() call. I find this syntax to be more succinct, more readable, and easier to maintain.
So that grouped data is sorted properly, sort the data ahead of time (while it is still in its simpler form). usort() with the spaceship operator (php7) will do all of the hardwork for you. Just be sure to pass the $groupsort variable into the function scope with use.
As you iterate the input array, isolate the identifying column value (and prepare it as necessary), then use it as a temporary key to determine the group in which the $row data should be stored.
Finally, use array_values() to remove the temporary identifying keys (if desired).
Code: (Demo)
$filter = "ORDER BY TODO_PRIO DESC";
$lookup = [
"ORDER BY TODO_REF DESC" => 0,
"ORDER BY TODO_PRIO DESC" => 2,
"ORDER BY TODO_DEAD DESC" => 3
];
$groupsort = isset($lookup[$filter]) ? $lookup[$filter] : 0;
$array = [
[1, "Do this task and make sure it gets done", 5, "2013-06-28 12:12:41"],
[1, "testing this show me 2", 5, "2029-02-23 17:27:20"],
[1, "This must also be done", 4, "2013-03-28 12:13:34"],
[2, "sdfsdgdfgdfgdfg", 3, "2013-05-30 13:53:23"],
[2, "Another priority", 3, "2013-03-28 11:11:11"]
];
// sort DESC on $groupsort column values
usort($array, function($a, $b)use($groupsort) { return $b[$groupsort] <=> $a[$groupsort]; });
// group by $groupsort column values
foreach ($array as $row) {
$id = $row[$groupsort]; // just to improve readability
if ($groupsort == 3) { $id = substr($id, 0, 10); } // remove time from datetime stamp
$result[$id][] = $row; // store the current value
}
var_export(array_values($result)); // reindex first level (remove temp keys);
Output:
array (
0 =>
array (
0 =>
array (
0 => 1,
1 => 'Do this task and make sure it gets done',
2 => 5,
3 => '2013-06-28 12:12:41',
),
1 =>
array (
0 => 1,
1 => 'testing this show me 2',
2 => 5,
3 => '2029-02-23 17:27:20',
),
),
1 =>
array (
0 =>
array (
0 => 1,
1 => 'This must also be done',
2 => 4,
3 => '2013-03-28 12:13:34',
),
),
2 =>
array (
0 =>
array (
0 => 2,
1 => 'sdfsdgdfgdfgdfg',
2 => 3,
3 => '2013-05-30 13:53:23',
),
1 =>
array (
0 => 2,
1 => 'Another priority',
2 => 3,
3 => '2013-03-28 11:11:11',
),
),
)

Sum multidimensional associative array values while preserving key names

There are many nice Q&A on Stackoverflow on how to take a multidimensional associative array and sum values in it. Unfortunately, I can't find one where the key names aren't lost.
For example:
$arr=array(
array('id'=>'1', 'amount'=>'5'),
array('id'=>'1', 'amount'=>'5'),
array('id'=>'2', 'amount'=>'1'),
array('id'=>'2', 'amount'=>'3')
);
I want the resulting array to look like this:
$result=array(
array('id'=>'1', 'amount'=>'10'),
array('id'=>'2', 'amount'=>'4')
);
Unfortunately the only thing I can figure out how to do is this:
$result = array();
foreach($arr as $amount){
if(!array_key_exists($amount['id'], $arr))
$result[$amount['id']] =0;
$result[$amount['id']] += $amount['amount'];
}
Which when echo'd as follows produces (notice the lack of the keys' words "id" and "amount"):
foreach($result as $id => $amount){
echo $id."==>".$amount."\n";
}
1==>10
2==>4
This is just to show that you already had the data you originally needed, though, the answer you accepted is a better way to deal with it.
You have the following to start with right?
$arr = array(
array('id'=>'1', 'amount'=>'5'),
array('id'=>'1', 'amount'=>'5'),
array('id'=>'2', 'amount'=>'1'),
array('id'=>'2', 'amount'=>'3')
);
Output
Array
(
[0] => Array
(
[id] => 1
[amount] => 5
)
[1] => Array
(
[id] => 1
[amount] => 5
)
[2] => Array
(
[id] => 2
[amount] => 1
)
[3] => Array
(
[id] => 2
[amount] => 3
)
)
Then you run it through the following algorithm:
$summedArr = array();
foreach ($arr as $amount) {
$summedArr['amount'][$amount['id']] += $amount['amount'];
$summedArr['id'][$amount['id']] = $amount['id'];
}
Now, disregarding the Notice warnings that are produced since you are referencing indexes that don't yet exist, this outputs the following:
Output
Array
(
[amount] => Array
(
[1] => 10
[2] => 4
)
[id] => Array
(
[1] => 1
[2] => 2
)
)
Do you see the keys, yet? Because I do.
Now iterate over the array:
foreach ($summedArr as $key => $value) {
echo $k . "==>" . $v . "\n";
}
Output
amount==>Array
id==>Array
That's not what you want, though. You want:
foreach ($summedArr as $key => $arr) {
foreach ($arr as $v) {
echo $key . "==>" . $v;
}
}
Why not use that method, and then reconstruct the array you want at the end?
$results = array();
foreach ($arr as $id=>$amount) {
$results[] = array('id' => $id, 'amount' => $amount);
}
Any other way of doing this would be more computationally expensive.

Categories