View Full Version : Merging Multi-dimensional arrays
jdadwilson
09-10-2013, 06:08 AM
I have need to merge a variable number of multi-dimensional associative arrays into a larger array structure. Here is a json representation of one of the arrays...
"HrlyInfo":{"3":{"ID":"210","Description":"Consultation\/Programming","Date":"2013-07-01","EmpNum":"A079","StaffDesc":"Professional Staff II","Hours":"1.00","Rate":95,"Comment":"No comment"}}
My problem is that only the last array "3" is included. All of the associative tags are the same. I have tried array_merge but the same thing happens.
I would really like something like the following...
"HrlyInfo":
{"1":{"ID":"210","Description":"Consultation\/Programming","Date":"2013-07-01","EmpNum":"A079","StaffDesc":"Professional Staff III","Hours":"1.00","Rate":95,"Comment":"No comment"}},{"2":{"ID":"210","Description":"Consultation\/Programming","Date":"2013-07-01","EmpNum":"A079","StaffDesc":"Professional Staff II","Hours":"2.00","Rate":100,"Comment":"No comment"}},{"3":{"ID":"210","Description":"Consultation\/Programming","Date":"2013-07-01","EmpNum":"A079","StaffDesc":"Professional Staff I","Hours":"3.00","Rate":110,"Comment":"No comment"}}
Any suggestions?
TIA
jDadwilson
Your question is unclear.
Please provide more information, and be as specific as possible.
What do you want to accomplish? What have you already tried? What problems did you encounter?
Please be sure that you have included all relevant code.
You might also consider making a reduced test case (http://css-tricks.com/reduced-test-cases/) that demonstrates your problem.
What format is the data in to start with? is it json? php arrays?
What have you already tried (how did you get your "wrong" result)?
From your initial description, I would think that you could simply do
<?php
$HourlyInfo = array(
$array_no_1
,$array_no_2
,$array_no_3
);
djr33
09-10-2013, 06:40 AM
What is the goal of merging the arrays? array_merge() will take all items from Array1 and all items from Array2 (and so forth) and then create a new array that includes all of those items on a single level. That doesn't seem to be what you want from the description, but you said you were trying that function.
james438
09-10-2013, 02:27 PM
This should help you get started:
<?php
$HrlyInfo1=array(1 =>array(
ID => '210',
Description => 'Consultation\/Programming',
date => '2013-07-01',
EmpNum => 'A079',
StaffDesc => 'Professional Staff III',
Hours => '1.00',
Rate => '95',
Comment => 'No comment',
));
$HrlyInfo2=array(2 =>array(
ID => '210',
Description => 'Consultation\/Programming',
date => '2013-07-01',
EmpNum => 'A079',
StaffDesc => 'Professional Staff II',
Hours => '2.00',
Rate => '100',
Comment => 'No comment',
));
$HrlyInfo3=array(3 =>array(
ID => '210',
Description => 'Consultation\/Programming',
date => '2013-07-01',
EmpNum => 'A079',
StaffDesc => 'Professional Staff I',
Hours => '3.00',
Rate => '110',
Comment => 'No comment',
));
$HrlyInfo=$HrlyInfo1+$HrlyInfo2+$HrlyInfo3;
echo"<pre>";
print_r($HrlyInfo);
echo"</pre>";
?>
jdadwilson
09-10-2013, 05:30 PM
It is a little difficult to 'explain' the need as it is a very critical part of an invoicing system for architects and engineers (www.archinvoice.com) that I am converting from VB to a web based system.
Basically, there are db records for the employees that record the hours worked on a project and phase of the project. Each employee additionally has a classification that indicates their hourly rate. To create the invoice I display the total hours worked for each classification, the classification rate, and the total charge.
Further, a project may bill a client on a square foot basis or on a fixed fee basis by phase (construction documents, design development, etc.). For a billing period there are usually multiple projects with multiple phases so it is not just a one time check of the db.
To answer some of the specific questions...
The data are in a db and are used to build the needed individual arrays (9 total for company info, project info, hourly info, etc.) which are then combined into a single larger array and stored in the db in json format. Those with just single level data are no problem (e.g., company info), but those with multi level data (e.g. hourly data) are the issue.
Because the generated arrays are dynamic doing something like
$HourlyInfo = array($array_no_1,$array_no_2,$array_no_3);
is not possible. There may only be an $array_no_1 or there might be an $array_no_12 and/or anything in between.
The code for the inner loop is
$Hrly_Array['Hours'] = $row_hrly['SUM(hrs_Hours)'];
I have also tried...
$Hrly_Array['Phase']['Hours'] = $row_hrly['SUM(hrs_Hours)'];
but that only gives the result of the last record.
I think the solution is to define the ['Phase'] level to be the record number or something like that.
Thanks for your input.
jdadwilson
IIUC, you want to create a single array that contains one or more component arrays.
Do these component arrays need to be labeled (i.e., your example shows "1"=>{} - would it make any difference if the arrays had random numbers (or weren't numbered at all))?
Are you having any difficulties retrieving the data from the DB (it sounds like not)?
Most importantly, you are referencing code when you explain things, but you are not actually showing us the code. This does not help - in fact, it can add to the confusion. Please post all relevant code (even if it doesn't work properly right now). This will help us understand the problem.
If there is any sensitive information in your code, you can ******** it before posting. If you have a lot of code, try to reduce it to only the relevant part (for example, if your DB queries are working properly, then you don't need to show us that code - just describe the result set that you're using).
I think a variation of my initial suggestion would work.
<?php
# psuedo-code #
if( $array_1_is_needed ){
$array_1 = /* build array */;
// add array to collection
$all_arrays[] = $array_1;
}
// same for array_2, etc..
jdadwilson
09-10-2013, 09:18 PM
Your example is correct generally speaking...
if( $array_1_is_needed ){
$array_1 = /* build array */;
// add array to collection
$all_arrays[] = $array_1;
}
// same for array_2, etc..
What I specifically do is...
build $InvInfo array
build $ProjInfo array
.
.
.
build $ExpsInfo array
build $AdjsInfo array
$inv_Array = array("InvInfo" => $InvInfo, "ProjInfo" => $ProjInfo, ... "ExpsInfo" => $ExpsInfo, "AdjsInfo" => $AdjsInfo);
The problem comes with the "..." arrays which are within themselves multi dimensional.
Here is a small snippet of the code...
<?php
// Select all hour worked on a project within the time period.
$query_STR = "SELECT * FROM hoursworked WHERE hrs_Project = ? AND hrs_Date >= ? AND hrs_Date <= ? ORDER BY hrs_Phase";
$query_HRS = $db->prepare($query_STR);
$query_HRS->execute(array($proj, BEGDATE, ENDDATE));
if ($query_HRS->rowCount() != 0)
{ // Select all hourly phase codes
$query_STR = "SELECT * FROM phasecodes WHERE phase_Code >= ? AND phase_Code <= ? ORDER BY phase_Code";
$query_PHS = $db->prepare($query_STR);
$query_PHS->execute(array(200, 299));
while ($row_phase = $query_PHS->fetch(PDO::FETCH_ASSOC))
{ // Isolate phase code and description
$sCode = $row_phase['phase_Code'];
$sDescription = $row_phase['phase_Description'];
// Select the hours worked for the project phase within the date range and sum the hours for each staff code
$query_STR = "SELECT hrs_Date, hrs_EmpNum, hrs_StaffCode, SUM(hrs_Hours) FROM hoursworked
WHERE hrs_Project = ? AND hrs_Phase = ? AND hrs_Date >= ? AND hrs_Date <= ?
GROUP BY hrs_StaffCode ORDER BY hrs_StaffCode";
$query_HRS = $db->prepare($query_STR);
$query_HRS->execute(array($proj, $sCode, BEGDATE, ENDDATE));
while ($row_hrly = $query_HRS->fetch(PDO::FETCH_ASSOC))
{ // Select the staffcode info base on the found rate
$query_STR = "SELECT * FROM staffcodes WHERE staff_Code = ?";
$query_STF = $db->prepare($query_STR);
$query_STF->execute(array($sRate));
$row_staff = $query_STF->fetch(PDO::FETCH_ASSOC);
// Build the information for the invoice array
$Hrly_Array['?']['Phase'] = $sCode;
$Hrly_Array['?']['Description'] = $sDescription;
$Hrly_Array['?']['Date'] = $row_hrly['hrs_Date'];
$Hrly_Array['?']['EmpNum'] = $row_hrly['hrs_EmpNum'];
$Hrly_Array['?']['StaffDesc'] = $row_staff['staff_Description'];
$Hrly_Array['?']['Hours'] = $row_hrly['SUM(hrs_Hours)'];
$Hrly_Array['?']['Rate'] = $sRate;
$Hrly_Array['?']['Comment'] = "No comment";
} // End of While for hoursworked
} // End of While for phases
}
?>
Because there can be multiple staff members (each with potentially different pay grades) working on a project-phase there needs to be multiple $Hrly_Array entries in the main array.
Some way I need to include the ['?'] (that is not in the real code, just an example) so that they are distinct and orderly. Using an associate name (e.g., ['Phase']) does not make them distinct and so the first ones get overwritten with the last one. Using something like the staff code (e.g., [$staffCode]) does not make them orderly (i.e., '1', '3', '5') and thus makes it cumbersome to retrieve the information for printing.
What would be nice is to be able to build the info into
$Phase_Array['Hours'] = $row_hrly['SUM(hrs_Hours)'] and then...
$Hrly_Array = $Hrly_Array + $Phase_Array after each loop through the code, and do so without destroying the previous information.
This is a very complex issue and hard for many to comprehend. This system was originally developed some 25 years ago in MS Excel using macros, then updated to VBA, then rewritten in VB. I am now in the process of converting it to a web-based application.
Any assistance you can provide is greatly appreciated.
jdadwilson
Because there can be multiple staff members (each with potentially different pay grades) working on a project-phase there needs to be multiple $Hrly_Array entries in the main array.
Some way I need to include the ['?'] (that is not in the real code, just an example) so that they are distinct and orderly. Using an associate name (e.g., ['Phase']) does not make them distinct and so the first ones get overwritten with the last one. Using something like the staff code (e.g., [$staffCode]) does not make them orderly (i.e., '1', '3', '5') and thus makes it cumbersome to retrieve the information for printing.
In php, you can append to an array using [] - if you don't specify an array key, PHP assigns a numeric key (equal to the greatest existing numeric key +1, or zero if no numeric keys yet exist). So, your while loop would become something like this:
<?php
# ... snip ... #
$Hrly_Array = array(); //<-- this may or may not be necessary,
// depending on which version of PHP you are running
while( $row_hrly = $query_HRS->fetch( PDO::FETCH_ASSOC ) ){
$query_STR = "SELECT * FROM staffcodes WHERE staff_Code = ?";
$query_STF = $db->prepare( $query_STR );
$query_STF->execute(array($sRate));
$row_staff = $query_STF->fetch(PDO::FETCH_ASSOC);
// create a new item in the array
$Hrly_Array[] = array(
'Phase' => $sCode
'Description' => $sDescription
'Date' => $row_hrly['hrs_Date']
'EmpNum' => $row_hrly['hrs_EmpNum']
'StaffDesc' => $row_staff['staff_Description']
'Hours' => $row_hrly['SUM(hrs_Hours)']
'Rate' => $sRate
'Comment' => "No comment"
); // end new array item
// on the first loop, this new array will be stored in $Hrly_Array[0]
// the second will be in $Hrly_Array[1]
// etc.
}
# ... snip ... #
going back to this:
Using something like the staff code (e.g., [$staffCode]) does not make them orderly (i.e., '1', '3', '5') and thus makes it cumbersome to retrieve the information for printing.
Actually, I can see a distinct advantage to using the staff code as the array key: it makes looking up a particular employee easy. As for retrieving the information, you can use a foreach{} (http://php.net/foreach) loop to retrieve each item from an array in turn, without knowing the keys.
jdadwilson
09-11-2013, 04:40 AM
It is amazing how great minds (at least yours) think alike. I went back and looked at the old VB code and that is exactly what I did some 15 years ago. I haven't tried it yet but it should do the trick.
Thanks for all your assistance.
jdadwilson
It is amazing how great minds (at least yours) think alike.
Actually, I only have one mind (that I know of). But thanks! I think it's great, too.
I went back and looked at the old VB code and that is exactly what I did some 15 years ago.
When all else fails, read the manual! :D
Thanks for all your assistance.
You are quite welcome. Post again if you have any more trouble.
Powered by vBulletin® Version 4.2.2 Copyright © 2021 vBulletin Solutions, Inc. All rights reserved.