PHP array reformat to highchart json ob - php

I am try to format an array to a JSON object that highcharts supports. My array from the database is as follows:
Array
(
[0] => Array
(
[Group_ID] => 1
[Name] => A line graph
[month] => 4
[amount] => 7700
)
[1] => Array
(
[Group_ID] => 2
[Name] => B Line graph
[month] => 4
[amount] => 390
)
[2] => Array
(
[Group_ID] => 1
[Name] => A line graph
[month] => 5
[amount] => 5000
)
[3] => Array
(
[Group_ID] => 2
[Name] => B line graph
[month] => 5
[amount] => 210
)
)
I need to create an array like this to be able to create a highchart compatible JSON object:
Array
(
[0] => Array
(
[name] => A revenue
[data] => Array
(
[4] => 7700 //amount for the fourth month
[5] => 5000 //amount for the fifth month
)
)
[1] => Array
(
[name] => B revenue
[data] => Array
(
[4] => 390 //amount for the fourth month
[5] => 210 //amount for the fifth month
)
)
)
I have managed to come up with this array using my foreach but I cant seem to find a way to do it correctly:
Array
(
[0] => Array
(
[name] => A line graph
[amount] => 7700
[month] => 4
)
[1] => Array
(
[name] => B line graph
[amount] => 390
[month] => 4
)
[2] => Array
(
[name] => A line graph
[amount] => 5000
[month] => 5
)
[3] => Array
(
[name] => B line graph
[amount] => 210
[month] => 5
)
)
My foreach:
foreach ($data as $key => $value) {
$r[] = [
'name' => $value['Line_GraphName'],
'data' => $value['amount'],
'month' => $value['month']
];
}

You can create it very simply like this:
foreach ($data as $value) {
$r[$value['Group_ID']]['name'] = $value['Line_GraphName'];
$r[$value['Group_ID']]['data'][$value['month']] = $value['amount'];
}
Loop and create a result with Group_ID as the key and add the name key and value
Add data array and append month as key and amount as value
If you don't like having Group_ID as the key and want to re-index:
$r = array_values($r);

The solution using array_walk and array_values functions:
$result = [];
array_walk($data, function($v) use(&$result) {
$key = $v['Group_ID'] . $v['Name'][0]; // compound key: "group_id + revenue's prefix"
if (!isset($result[$key])) {
$result[$key] = ['name' => $key[1] . " Revenue", 'data' => [$v['month'] => $v['amount']]];
} else {
$result[$key]['data'][$v['month']] = $v['amount'];
}
});
print_r(array_values($result));
The output:
Array
(
[0] => Array
(
[name] => A Revenue
[data] => Array
(
[4] => 7700
[5] => 5000
)
)
[1] => Array
(
[name] => B Revenue
[data] => Array
(
[4] => 390
[5] => 210
)
)
)

Related

Get sum of subarray column for indexed rows

I have an array of customers/people with a subarray of projects pertaining to that customer. Projects come in two types "typeJob" or "typePipeline". I need to sum the values of individual columns in the projects subarray (specifically columns 5, 6, 7 - representing revenue for month 1, month 2, and month 3) by Client.
I have tried various possible avenues including the one below, but I seem to always end up either testing if the condition is satisfied for the array as a whole rather than for each row - or if I go the way of for each loops generate errors because either there's an array/single value mismatch or the condition just doesn't do anything.
Here is what I have tried most recently. It works in the sense that it checks if "typeJob" is in the array but then sums all rows (even those without "typeJob") if "typeJob" is found for any of the Client's projects. I want to exclude rows where "typeJob" is not found.
foreach ($arrays as $row) {
$indexJob = array_search('typeJob', array_column($row['projects'],0));
if ($indexJob !== false) {
$job_total1[$row['Client']] = array_sum(array_column($row['projects'],5));
$job_total2[$row['Client']] = array_sum(array_column($row['projects'],6));
$job_total3[$row['Client']] = array_sum(array_column($row['projects'],7));
}
}
And here is the array:
(
[331] => Array
(
[KeyAccountID] => 1234
[KeyAccountName] => John Lennon
[ClientID] => 9999
[Client] => BBC
[projects] => Array
(
[0] => Array
(
[0] => typePipeline
[1] => 915
[2] => Zyxeldy
[3] =>
[4] =>
[5] => 15000
[6] =>
[7] =>
[8] =>
)
[1] => Array
(
[0] => typeJob
[1] => 956
[2] => Awesome project, Step 1
[3] =>
[4] =>
[5] => 1833.3333
[6] => 1833.3333
[7] => 1833.3333
[8] =>
)
[2] => Array
(
[0] => typePipeline
[1] => 957
[2] => Awesome project, Step 2
[3] =>
[4] =>
[5] => 7000
[6] =>
[7] =>
[8] =>
)
)
)
[344] => Array
(
[KeyAccountID] => 1234
[KeyAccountName] => John Lennon
[ClientID] => 9998
[Client] => ABC
[projects] => Array
(
[0] => Array
(
[0] => typePipeline
[1] => 487
[2] => CRM integration
[3] =>
[4] =>
[5] =>
[6] => 98750
[7] => 98750
[8] =>
)
[1] => Array
(
[0] => typeJob
[1] => 839
[2] => Data Warehouse
[3] =>
[4] =>
[5] =>
[6] => 11643.0601
[7] =>
[8] =>
)
)
)
[350] => Array
(
[KeyAccountID] => 1236
[KeyAccountName] => Ringo Starr
[ClientID] => 9997
[Client] => XYY
[projects] => Array
(
[0] => Array
(
[0] => typeJob
[1] => 867
[2] => Data Mining
[3] =>
[4] =>
[5] => 10000
[6] =>
[7] =>
[8] =>
)
)
)
[351] => Array
(
[KeyAccountID] => 1235
[KeyAccountName] => Poul McCartney
[ClientID] => 9996
[Client] => XYZ
[projects] => Array
(
[0] => Array
(
[0] => typePipeline
[1] => 715
[2] => XYZ, CSM
[3] =>
[4] =>
[5] => 22083.3333
[6] => 22083.3333
[7] => 22083.3333
[8] =>
)
)
)
etc.
You could filter the $row['projects'] array before summing the values:
foreach ($arrays as $row) {
$typeJobs = array_filter($row['projects'], function ($v) { return $v[0] == 'typeJob'; });
$job_total1[$row['Client']] = array_sum(array_column($typeJobs,5));
$job_total2[$row['Client']] = array_sum(array_column($typeJobs,6));
$job_total3[$row['Client']] = array_sum(array_column($typeJobs,7));
}
It may be quicker to just loop through them and keep a running total...
foreach ($arrays as $row) {
$totals = [0,0,0];
foreach ( $row['projects'] as $project ) {
if ( $project[0] == 'typeJob' ) {
$totals[0] += $project[5];
$totals[1] += $project[6];
$totals[2] += $project[7];
}
}
$job_total1[$row['Client']] = $totals[0];
$job_total2[$row['Client']] = $totals[1];
$job_total3[$row['Client']] = $totals[2];
}
it doesn't look as slim as using the array_... methods, but this only processes the array once instead of once for each call.

How to access object properties within an array

I have some code that generates an array with an object in it and I want to access the object values.
$results = array();
$std_arr = array();
$data['examlist'] = $this->exam_model->get($exam);
foreach ($student_array as $key => $value) {
$std_arr[] = $value->student_id;
$results[] = $this->student_model->get_single_student_result($value->student_id);
}
and When i log the results i got
Array
(
[0] => Array
(
[0] => stdClass Object
(
[exam_schedule_id] => 14
[get_marks] => 23.00
[id] => 1
[exam_id] => 1
[teacher_subject_id] => 1
[name] => GEO
[teacher_id] => 16
[subject_id] => 1
[code] => Geography
)
)
[1] => Array
(
[0] => stdClass Object
(
[exam_schedule_id] => 14
[get_marks] => 0.00
[id] => 1
[exam_id] => 1
[teacher_subject_id] => 1
[name] => GEO
[teacher_id] => 16
[subject_id] => 1
[code] => Geography
)
How can I access these 'stdClass Object' property?

How to remove duplicate data in an array?

I have the following array:
Array
(
[0] => Array
(
[Import] => Array
(
[product_id] => 1
[id] => 1
[category_id] => 1
[amount] => 50
[cost] => 8320
[paid] => 0
[comment] => transportation and others cost: 100
[created] => 2015-06-22 12:09:20
)
[0] => Array
(
[total_sell] => 6
)
)
[1] => Array
(
[Import] => Array
(
[product_id] => 2
[id] => 2
[category_id] => 2
[amount] => 15
[cost] => 3000
[paid] => 0
[comment] =>
[created] => 2015-06-22 12:10:36
)
[0] => Array
(
[total_sell] => 1
)
)
[2] => Array
(
[Import] => Array
(
[product_id] => 1
[id] => 3
[category_id] => 1
[amount] => 15
[cost] => 2000
[paid] => 0
[comment] =>
[created] => 2015-06-22 12:10:58
)
[0] => Array
(
[total_sell] => 6
)
)
[3] => Array
(
[Import] => Array
(
[product_id] => 1
[id] => 4
[category_id] => 1
[amount] => 50
[cost] => 8000
[paid] => 0
[comment] =>
[created] => 2015-06-23 01:10:10
)
[0] => Array
(
[total_sell] => 6
)
)
)
I want to remove duplicate entry of [Import][product_id]. So my expected result is :
Array
(
[0] => Array
(
[Import] => Array
(
[product_id] => 1
[id] => 1
[category_id] => 1
[amount] => 50
[cost] => 8320
[paid] => 0
[comment] => transportation and others cost: 100
[created] => 2015-06-22 12:09:20
)
[0] => Array
(
[total_sell] => 6
)
)
[1] => Array
(
[Import] => Array
(
[product_id] => 2
[id] => 2
[category_id] => 2
[amount] => 15
[cost] => 3000
[paid] => 0
[comment] =>
[created] => 2015-06-22 12:10:36
)
[0] => Array
(
[total_sell] => 1
)
)
)
Would you write a function to filter this type of array and produce expected result. I have been googling for 2 days but no luck.
This is a handy one liner that should do the trick:
$unique= array_map("unserialize", array_unique(array_map("serialize", $original)));
If the underlying arrays are not identical, that won't work, in which case I think you could do:
$unique = array_intersect_key($original ,
array_unique(
array_map(function($item) {
return $item['Import']['product_id'];
}, $original)
)
);
Tested: http://sandbox.onlinephpfunctions.com/code/8aee5cbd614e0ddd1a03dfaa7e98c72fbbe7d68d
Here is a quick stable sort and reduce which runs in linearithmic time. First-encountered product Id's are kept, and entries with duplicate product Id's are ignored.
// Stable sort
sort($in);
// Reduce
$out = array_reduce($in, function(&$acc, &$item){
if($item['Import']['product_id'] !== #$acc[sizeof($acc)-1]['Import']['product_id']) {
$acc[] = $item;
}
return $acc;
}, []);
Demo: http://ideone.com/BP0eUJ
Update: Here is an even better linear-time algorithm that does the same as above using a fast "hash table" lookup. Again, the first-encountered product Id is kept and subsequent ones of the same Id are ignored.
$out = [];
$hashTable = [];
foreach($in as $item) {
$pid = $item['Import']['product_id'];
if(!isset($hashTable[$pid])) {
$out[] = $item;
$hashTable[$pid] = true;
}
}
Demo: http://ideone.com/5RF0og

Replace numeric array keys with associative keys from array

I have a dataset similar to this in which I am trying to replace the numeric key values within DATA to the corresponding values in COLUMNS. I can do this in a loop but I don't think I'm doing it in the most efficient way possible. Can anyone suggest any nice functions that I haven't considered to accomplish this?
Existing Style
stdClass Object
(
[COLUMNS] => Array
(
[0] => MATCHID
[1] => SEASON
[2] => COMPETITION
[3] => ROUNDID
[4] => ROUNDSORT
[5] => ROUNDNAME
)
[DATA] => Array
(
[0] => Array
(
[0] => 141627
[1] => 2013/2014
[2] => The Scottish Cup
[3] => 18
[4] => 11
[5] => Final
)
[1] => Array
(
[0] => 140895
[1] => 2013/2014
[2] => The Scottish Cup
[3] => 16
[4] => 10
[5] => Semi-Final
)
)
)
Desired Style
stdClass Object
(
[COLUMNS] => Array
(
[0] => MATCHID
[1] => SEASON
[2] => COMPETITION
[3] => ROUNDID
[4] => ROUNDSORT
[5] => ROUNDNAME
)
[DATA] => Array
(
[0] => Array
(
[MATCHID] => 141627
[SEASON] => 2013/2014
[COMPETITION] => The Scottish Cup
[ROUNDID] => 18
[ROUNDSORT] => 11
[ROUNDNAME] => Final
)
[1] => Array
(
[MATCHID] => 140895
[SEASON] => 2013/2014
[COMPETITION] => The Scottish Cup
[ROUNDID] => 16
[ROUNDSORT] => 10
[ROUNDNAME] => Semi-Final
)
)
)
foreach ($data->DATA as $key => $array) {
$data->DATA[$key] = array_combine($data->COLUMNS, $array);
}
$data is the object you showed.
Loop trough the data and combine the keys with the data, see array_combine
$data->DATA = array_map(function (array $entry) use ($data) {
return array_combine($data->COLUMNS, $entry);
}, $data->DATA);

php based on conditions create multiple arrays from one array

Initial array
Array
(
[0] => Array
(
[RecordDay] => 23
[Amount] => 1.50
[DocumentName] => bank stmt
[DocumentNumber] => 1
)
[1] => Array
(
[RecordDay] => 17
[Amount] => 0.21
[DocumentName] => invoice
[DocumentNumber] => 2
)
[2] => Array
(
[RecordDay] => 17
[Amount] => 1.00
[DocumentName] => invoice
[DocumentNumber] => 2
)
)
From all subarrays, where [RecordDay], [DocumentName] and [DocumentNumber] are the same want to create new array.
For keys [1] and [2] [RecordDay], [DocumentName] and [DocumentNumber] are the same.
So as a result want to get this
Array
(
[0] => Array
(
[RecordDay] => 23
[Amount] => 1.50
[DocumentName] => bank stmt
[DocumentNumber] => 1
)
)
Array
(
[0] => Array
(
[RecordDay] => 17
[Amount] => 0.21
[DocumentName] => invoice
[DocumentNumber] => 2
)
[1] => Array
(
[RecordDay] => 17
[Amount] => 1.00
[DocumentName] => invoice
[DocumentNumber] => 2
)
)
But no idea how to do that
Made like this
$first_loop = true;
foreach($initial_array as $key => $one_dimensional_array){
if($first_loop == true){
$new_array1['RecordDay'][] = $one_dimensional_array['RecordDay'];
$first_loop = false;
}
if($first_loop == false){
if( in_array( $one_dimensional_array['RecordDay'], $new_array1['RecordDay'] ) ){
$new_array1['RecordDay'][] = $one_dimensional_array['RecordDay'];
}
else{
$new_array2['RecordDay'][] = $one_dimensional_array['RecordDay'];
}
}//if($first_loop == false){
}//foreach($initial_array as $key => $one_dimensional_array){
Got
Array
(
[RecordDay] => Array
(
[0] => 23
[1] => 23
)
[DocumentName] => Array
(
[0] => bank stmt
[1] => bank stmt
)
[DocumentNumber] => Array
(
[0] => 1
[1] => 1
)
)
Array
(
[RecordDay] => Array
(
[0] => 17
[1] => 17
)
[DocumentName] => Array
(
[0] => invoice
[1] => invoice
)
[DocumentNumber] => Array
(
[0] => 2
[1] => 2
)
)
But this is not what want. Any ideas what need to change?
Try like this,
$temp_array=array();
foreach($initial_array as $arr){
$temp_array[$arr['RecordDay'].",".$arr['DocumentNumber'].",".$arr['DocumentName']] []=$arr; //here it will **ADD** a new array in a key 'RecordDay,DocumentNumber,DocumentName' format. e.g. [23,1,'bank stmt'] , [17,2,'invoice'].
}
Now you need to process $temp_array to get individual arrays
foreach ($temp_array as $separate_array){
print_r($separate_array); //process your new array here one by one.
}
Working DEMO

Categories