PHP - Incrementally add array value - php

Basically I have this from a query:
Array
(
[0] => Array
(
[period] => 2014-03
[val] => 2.19
[type] => TypeX
),
[1] => Array
(
[period] => 2014-03
[val] => 2.02
[type] => TypeY
)
)
Using a foreach loop to populate another array we will call DATA, I want the to get the following:
Array
(
[TypeX] => Array
(
[2014-03] => 2.19
)
[TypeY] => Array
(
[2014-03] => 2.02
)
)
The whole thing is looped because my query needs to run each time for a different period. Current exemple, second loop would run for 2014-04. My problem is when I arrive for the 2nd time at my DATA array, I want this:
Array
(
[TypeX] => Array
(
[2014-03] => 2.19
[2014-04] => 1.10
)
[TypeY] => Array
(
[2014-03] => 2.02
[2014-04] => 4.74
)
)
My code is roughly like this:
$data = array();
foreach($graph_period as $period){
$rows = Queryfunction($period,$WHERE,$byType);
foreach($rows as $row){
$data[$row['type']] = array($row['period']=>$row['val']);
}
}
Because the key of the first level (TypeX, TypeY) are the same, the valei is overwritten. How am I to append the array instead of overwriting ?

foreach($rows as $row){
$data[$row['type']][$row['period']] = $row['val']);
}

You only need to change a tiny bit. Inside the foreach where you set the value:
if( !isset($date[$row['type']]) ) {
$data[$row['type']] = array();
}
$data[$row['type']][$row['period']] = $row['val'];
So, you create the array only if it does not exist.

Related

Adding to a multidimensional associative array (in PHP)

I'm returning an associative array via PDO that has the structure:
Array
(
[0] => Array
(
[pesttopicID] => 42
[sPestName] => CMSM Trap Surveying and Pest Management
[quizID] => 609
[bTier1] => 1
[sDesc] => Workshop assessment
)
[1] => Array
(
[pesttopicID] => 34
[sPestName] => Trap Surveyor
[quizID] => 451
[bTier1] => 1
[sDesc] => Competency for CM OAP
)
)
I want to add a key-value pair to the "inner" array, but all my attempts of trying to use posted solutions to the generic issue of adding to an associative array...
:
$results = $statement->fetchAll(PDO::FETCH_ASSOC);
$newkey='myNewKey';
$newval='myNewValue';
foreach($results as $row){
$results[][$newkey] = $newval;
foreach ($row as $key=>$value){
... some reporting stuff
}
}
...result in the pair being added to the "outer" array e.g.
Array
(
[0] => Array <---- I want the new pair in this "inner" array
(
[pesttopicID] => 42
[sPestName] => CMSM Trap Surveying and Pest Management
[quizID] => 609
[bTier1] => 1
[sDesc] => Workshop assessment
)
[1] => Array <---- I want the new pair in this "inner" array
(
[pesttopicID] => 34
[sPestName] => Trap Surveyor
[quizID] => 451
[bTier1] => 1
[sDesc] => Competency for CM OAP
)
[2] => Array
(
[myNewKey] => myNewValue
)
)
Is this possible?
Thanks/Tom
You have to it like below:-
$newkey='myNewKey';
$newval='myNewValue';
foreach($results as &$row){ //use reference variable
$row[$newkey] = $newval;// remove the second foreach if not necessary
//if second foreach is necessary then add it no problem
}
Output:-https://eval.in/856983
Or you can do like this also:-
$newkey='myNewKey';
$newval='myNewValue';
foreach($results as $key=>$row){ //use key now
$results[$key][$newkey] = $newval;// remove the second foreach if not necessary
//if second foreach is necessary then add it no problem
}
Output:-https://eval.in/856987

PHP Nested foreach with Key

I have been trying to work this out for two days now and am hitting a brick wall. I have a skyscanner array that has flight itineraries where I have the flight
Leg - being Itineraries -> OutboundLegId -
and also the legs which shows the flight number - being
Legs -> FlightNumbers -> FlightNumber.
What I am trying to achieve is to display the Itinerary and then join the Flight Number on to that. But no matter what I try I cannot get this to work. I have read all about Keys on here and tried loads of examples but am coming up with nothing. Can someone point me in the right direction please?
Example arrays below
[Itineraries] => Array
(
[0] => Array
(
[OutboundLegId] => 13542-1610140610-29-0-13445-1610141240
[InboundLegId] => 13445-1610211340-29-0-13542-1610211640
[PricingOptions] => Array
(
[0] => Array
(
[Agents] => Array
(
[0] => 2174187
)
[QuoteAgeInMinutes] => 31
[Price] => 200.98
[DeeplinkUrl] => http://partners.api.skyscanner.net/apiservices/deeplink/v2?_cje=5JlLCgyPUKY0hT8T0Ybh6dL0Xf0htAiHTFX7RU79eeI3XvrsxvEqP1QUJAoHiHRd&url=http%3a%2f%2fwww.apideeplink.com%2ftransport_deeplink%2f4.0%2fUK%2fen-gb%2fGBP%2fcook%2f2%2f13542.13445.2016-10-14%2c13445.13542.2016-10-21%2fair%2fairli%2fflights%3fitinerary%3dflight%7c-32294%7c1152%7c13542%7c2016-10-14T06%3a10%7c13445%7c2016-10-14T12%3a40%2cflight%7c-32294%7c1153%7c13445%7c2016-10-21T13%3a40%7c13542%7c2016-10-21T16%3a40%26carriers%3d-32294%26passengers%3d1%2c0%2c0%26channel%3ddataapi%26cabin_class%3deconomy%26facilitated%3dfalse%26ticket_price%3d200.98%26is_npt%3dfalse%26is_multipart%3dfalse%26client_id%3dskyscanner_b2b%26request_id%3d3bc96bda-fd7c-403a-b841-2ccc3c26071d%26commercial_filters%3dfalse%26q_datetime_utc%3d2016-09-29T08%3a18%3a27
)
[Legs] => Array
(
[0] => Array
(
[Id] => 13542-1610140610-29-0-13445-1610141240
[SegmentIds] => Array
(
[0] => 1
)
[OriginStation] => 13542
[DestinationStation] => 13445
[Departure] => 2016-10-14T06:10:00
[Arrival] => 2016-10-14T12:40:00
[Duration] => 270
[JourneyMode] => Flight
[Stops] => Array
(
)
[Carriers] => Array
(
[0] => 105
)
[OperatingCarriers] => Array
(
[0] => 105
)
[Directionality] => Outbound
[FlightNumbers] => Array
(
[0] => Array
(
[FlightNumber] => 1152
[CarrierId] => 105
)
)
)
Assuming this is one big array and its called $data you can nest a couple of foreach loops.
I use foreach loops as I assume there are cases where this data structure get more complex than the one you show
foreach ( $data['Itineraries'] as $itin ) {
foreach ( $data['Legs'] as $legs) {
if ($legs['Id'] == $itin['OutboundLegId']) {
// we matched the itinerary with a leg
echo $legs['OutboundLegId'] . ' ' . $legs['FlightNumbers'][0]['FlightNumber'];
}
}
}
Use it as draft. Can't perform function without feedback.
Put proper arrays instead of {YOUR-ARRAY-WITH-LEGS} and {YOUR-ARRAY-WITH-ITINERARIES}
$sortedLegs = array_column('Id', {YOUR-ARRAY-WITH-LEGS});
$joinedArray = array_map(function($itinerary) use($sortedLegs){
if(array_key_exists($itinerary['OutboundLegId'],$sortedLegs)) {
$itinerary['legs'] = $sortedLegs[$itinerary['OutboundLegId']];
}
return $itinerary;
},{YOUR-ARRAY-WITH-ITINERARIES});

How can I filter an array to include only the most recent items for each id?

I have an array like below:
Array
(
[0] => Array
(
[clearing] => 160000
[paydate] => 2016-08-03
[latecharge] => 900
)
[1] => Array
(
[clearing] => 160000
[paydate] => 2016-08-04
[latecharge] => 950
)
[2] => Array
(
[clearing] => 160001
[paydate] => 2016-08-05
[latecharge] => 850
)
)
I am trying to keep the latest paydate of each clearing and remove the rest of the array.
For example, for clearing 160000, the latest paydate is 2016-08-04 and for 160001 the latest paydate is 2016-08-05 so my result array should be like below:
Array
(
[1] => Array
(
[clearing] => 160000
[paydate] => 2016-08-04
[latecharge] => 950
)
[2] => Array
(
[clearing] => 160001
[paydate] => 2016-08-05
[latecharge] => 850
)
)
How can I do this?
Loop over your array and group by the 'clearing' key. Each time you get to one where that 'clearing' is not set in your result array, set it to the current instance, or if it is set, replace it if the current instance is newer.
foreach ($clearings as $clearing) {
$id = $clearing['clearing'];
if (!isset($latest[$id]) || $latest[$id]['paydate'] < $clearing['paydate']) {
$latest[$id] = $clearing;
}
}
The comment from #jeroen makes a good point. If you (or future readers) are getting this array from a database, for example, it will most likely be more efficient to modify your query and do this in the db. The concept is called groupwise maximum, and there are some good answers with a few different ways to get it on this question.
Create a function that loops through the array.
function clearOldPaydates($array)
{
$cleaned = array();
foreach($array as $item)
{
// if it's the first item of this date we keep it
// if there is already an item with this date we only overwrite it if it's older
if(!isset($cleaned[$item['paydate']])
|| strtotime($item['paydate']] > $cleaned[$item['paydate'])
{
$cleaned[$item['paydate']] = $item;
}
}
// we return the array with numeric keys
return array_values($cleaned);
}

php array merge with value of parent array

I need to merge an array with value of parent array.
$testArr=unserialize('a:6:{s:5:"queue";a:2:{i:6;s:1:"5";i:5;s:1:"2";}s:3:"sum";a:2:{i:6;s:3:"765";i:5;s:3:"2.1";}s:7:"sumAccD";a:2:{i:6;s:3:"543";i:5;s:3:"3.1";}s:7:"sumAccC";a:2:{i:6;s:2:"54";i:5;s:3:"3.3";}s:7:"comment";a:2:{i:6;s:12:"test comment";i:5;s:6:"111222";}s:3:"yt0";s:0:"";}');
$ret = array();
foreach ($testArr as $pkey => $pval) {
if (is_array($pval)) {
foreach ($pval as $pvkey => $pvval) {
$ret[$pvkey] = array($pkey => $pvval);
}
}
}
echo '<pre>', print_r($ret), '</pre>';
In this case it prints out
Array
(
[6] => Array
(
[comment] => test comment
)
[5] => Array
(
[comment] => 111222
)
)
1
Unfortunally it print out only comment. I need to add other rows: queue,sum,sumAccD,sumAccC. Array must look like this:
Array
(
[6] => Array
(
[queue] => 5
[sum] => ''
....
[comment] => test comment
)
[5] => Array
(
[queue] => 2
[sum] => 2.1
....
[comment] => 111222
)
)
1
Please help merge them.
Thanks.
Look at this line:
$ret[$pvkey] = array($pkey => $pvval);
You're assigning the key to a new array every time, overwriting what was previously there.
In your case, 'comment' is the last key that is processed, so that's going to be the only key in the final array.
Instead of this, you could define a new array only once outside the inner for, like this:
$ret[$pvkey] = array();
And then assign your values to that array in the inner for loop as you would normally do (so no more creating arrays there!)
Problem solved by replacing
$ret[$pvkey] = array($pkey => $pvval);
with
$ret[$pvkey][$pkey] = $pvval;

Merge arrays together based on different values

I am having trouble thinking of the logic with the following problem:
I have the following array (has been snipped, as its much larger)
Array
(
[0] => Array
(
[code] => LAD001
[whqc] => GEN
[stocktag] => NONE
[qty] => 54
)
[1] => Array
(
[code] => LAD001
[whqc] => GEN
[stocktag] => NONE
[qty] => 6
)
[2] => Array
(
[code] => LAD004
[whqc] => HOLD
[stocktag] => NONE
[qty] => 6
)
)
I basically need to comebine all the keys in this array so that where the code, whqc and stocktag are the same, add the qty values together. With the example below, I need to end up with this:
Array
(
[0] => Array
(
[code] => LAD001
[whqc] => GEN
[stocktag] => NONE
[qty] => 60
)
[1] => Array
(
[code] => LAD004
[whqc] => HOLD
[stocktag] => NONE
[qty] => 6
)
)
As the first and second keys of the array had the same code, whqc and stocktag, the qty's have been added together into the one key.
Any ideas?
I would suggest combining the group values in to a hash, storing the full array under the hash as a key and if you have a duplicate, add the quantity, then do array_values() to pull the results.
$aggregated = array();
foreach ($records as $cRec) {
// The separator | has been used, if that appears in the tags, change it
$cKey = md5($cRec['code'] . '|' . $cRec['whqc'] . '|' . $cRec['stocktag']);
if (array_key_exists($cKey, $aggregated)) {
$aggregated[$cKey]['qty'] += $cRec['qty'];
} else {
$aggregated[$cKey] = $cRec;
}
}
// Reset the keys to numerics
$aggregated = array_values($aggregated);
I would try something like:
$output = array();
foreach($array as $details){
//make distinct key
$key = $details['code'].'_'.$details['whqc'];
if(!isset($output[$key])){
$output[$key] = $details;
}else{
$output[$key]['qty'] += $details['qty'];
$output[$key]['stocktag'] = $details['stocktag'];
}
}
$output = array_values($output);
print_r($output);
update: Orbling was first ;-)

Categories