Return aggregated array from input multidimensional array - php

I've got two inputs, an ID and multidimensional array
For example, let's say the ID = 5 and the array looks like this:
Array
(
[0] => stdClass Object
(
[year] => 2017
[value] => a:9:{i:5;b:1;i:38;b:1;i:40;b:1;i:42;b:1;i:44;b:1;i:29;b:1;i:46;b:1;i:27;b:1;i:48;b:1;}
)
[1] => stdClass Object
(
[year] => 2018
[value] => a:9:{i:31;b:1;i:5;b:1;i:25;b:1;i:16;b:1;i:27;b:1;i:29;b:1;i:12;b:1;i:14;b:1;i:34;b:1;}
)
[2] => stdClass Object
(
[year] => 2018
[value] => a:3:{i:12;b:1;i:14;b:1;i:16;b:1;}
)
)
I need to unserialize the value and aggregate the data yearly. For example of ID = 5, the output should look like this:
Array
(
[2017] => 1
[2018] => 1
)
Currently I've got so far as to unserialize the value part:
foreach($results as $object=>$result){
echo $result->year;
echo "<br>";
echo join(',', array_keys(unserialize($result->value)));
echo "<br>";
}
Please advise on how to move on from here.

After you unserialize the value, check if the element whose key is ID is set. If it is, increment a counter for the year.
$id = 5;
$output = array();
foreach ($results as $result) {
$value = unserialize($result->value);
if (!empty($value[$id])) {
if (isset($output[$result->year])) {
$output[$result->year]++;
} else {
$output[$result->year] = 1;
}
}
}
print_r($output);

Related

Merge array with same value [duplicate]

This question already has answers here:
PHP Unique Values from Column in Array
(5 answers)
Closed 5 months ago.
How to marge array result with same value, i was try array_unique but seems does not work for me
Code:
$row_content = mysql_fetch_assoc($sql);
$array = unserialize($row_content['content_id']);
foreach($array as $row) {
print_r($row);
}
Here is result
Array
(
[0] => v
[1] => 2040
)
Array
(
[0] => v
[1] => 526
)
Array
(
[0] => v
[1] => 200
)
Array
(
[0] => p
[1] => 2040
)
Array
(
[0] => p
[1] => 600
)
Need to merge [1] or 2040 in this example, also value V or P it does not matter here
Edit:
This is what i need to get as result
Array
(
[1] => 200
)
Array
(
[1] => 526
)
Array
(
[1] => 600
)
Array
(
[1] => 2040
)
If I don't misunderstood your requirements then this is what you need.
<?php
$ar1 = array(array('v',2040),array('v',526),array('v',200),array('v',2040),array('p',600));
$result = [];
foreach($ar1 as $k=>$v){
$result[]=$v[1];
}
$unique_v = array_unique($result);
print '<pre>';
print_r($unique_v);
print '</pre>';
?>
DEMO: https://3v4l.org/sGLlc
I don't exactly get what you are trying to say. But if you want to merge/add all the values of "p" and "v". You can do it like this:
$array = array(array('v',2040),array('v',526),array('v',200),array('v',2040),array('p',600));
$keeper = array();
foreach($array as $row){
if(array_key_exists($row[0],$keeper)){
$keeper[$row[0]] += $row[1];
}else{
$keeper[$row[0]] = $row[1];
}
}

Pushing a sub array into the same array

I am trying to put content of one array into the same array. Here I have an array $mclass with values such as
Array
(
[0] => stdClass Object
(
[room_id] => 1,3,5
[day] => 1
[class_teacher] => TEA-2014-2
[final_exam_date] => 2015-09-21
)
)
You can see I have room_id index with 1,3,5 value. Now, I want to explode the room_id and get duplicate of same array index data with change of room_id and push into the array. and finally delete the current array index such as [0]. Here I want the final result as.
Array
(
[0] => stdClass Object
(
[room_id] => 1
[day] => 1
[class_teacher] => TEA-2014-2
[final_exam_date] => 2015-09-21
)
[1] => stdClass Object
(
[room_id] => 3
[day] => 1
[class_teacher] => TEA-2014-2
[final_exam_date] => 2015-09-21
)
[2] => stdClass Object
(
[room_id] => 5
[day] => 1
[class_teacher] => TEA-2014-2
[final_exam_date] => 2015-09-21
)
)
Here is my code for the same:
if(count($mclass)>0)
{
foreach($mclass as $mclasskey=>$mclass_row)
{
/* Room ID Calculation */
if(isset($mclass[$mclasskey]))
{
$temp_room_id = explode(',',$mclass_row->room_id);
if(count($temp_room_id)>1)
{
foreach($temp_room_id as $trkey=>$tr)
{
if(!in_array($temp_room_id[$trkey], $morning_class_semester))
{
array_push($morning_class_semester,$temp_room_id[$trkey]);
}
}
if(count($morning_class_semester)>0)
{
foreach($morning_class_semester as $mcskey=>$mcs)
{
$index_count = count($new_test);
$test[$index_count] = $mclass[$mclasskey];
$test[$index_count]->room_id = $morning_class_semester[$mcskey];
array_push($new_test,$test[$index_count]);
}
unset($mclass[$mclasskey]);
}
}
}
}
}
The code below does what you're looking for using only arrays. So you'll have to change the array access operators to -> since you're accessing an object. I'd do so, but it would break the example, so I'll leave that up to you.
Code Explained:
Loop through array selecting each subarray (object in your case), explode on the $item('room_id') ... ($item->room_id in your case) ... and create sub arrays, via loop, from that using the data from the original using each key. Remove the original item (which has the combined room_ids) and combine the placeholder and original array.
<?php
//Establish some data to work with
$array = array(
array(
"room_id" => "1,3,5",
"day" => 1,
"class_teacher" => "TEA-2014-2",
"final_exam_date" => "2015-09-21",
));
foreach ($array as $key => $item) {
$placeholder = array();
$ids = explode(',',$item['room_id']);
if (count($ids) > 1) {
foreach ($ids as $id) {
$push = array(
'room_id' => $id,
'day' => $item['day'],
'class_teacher' => $item['class_teacher'],
'final_exam_date' => $item['final_exam_date']
);
array_push($placeholder, $push);
}
$array = array_merge($array, $placeholder);
unset($array[$key]);
}
}
var_dump($array);
?>

Multiple array data in php and get the SUM

I am using Codeigniter and I have a function like this .
function total_income(){
$data['total_income'] = $this->mod_products->total_income();
echo"<pre>";
print_r($data['total_income']);
}
The above code return an array like this.
Array
(
[0] => stdClass Object
(
[sub_product_price] => 1000
[quantity] => 1
)
[1] => stdClass Object
(
[sub_product_price] => 1000
[quantity] => 1
)
[2] => stdClass Object
(
[sub_product_price] => 50
[quantity] => 15
)
[3] => stdClass Object
(
[sub_product_price] => 500
[quantity] => 5
)
)
Now I want to get the [sub_product_price] and multiply that value with [quantity] .Then I want to get the array_sum. I don't have an idea how to do that. Could some one help me It would be grate ,
Cheers!! Rob
$sum = 0;
foreach ($array as $obj) {
$sum += ($obj->quantity * $obj->sub_product_price);
}
Add the all values after multiplication in an empty array and use array_sum() to get the final value.
$temp = array();
foreach($data['total_income'] as $in)
{
$temp[] = $in->sub_product_price * $in->quantity;
}
$total = array_sum($temp);
Explanation:
array_sum() returns the sum of all the values of an array.
Example,
$array = array(4,5,6);
echo array_sum($array); // 15

Combination of arrays

I have tried to get the below code to work for a good couple of hours, but just don't succeed.
I have this date array:
Array ( [0] => Array ( [0] => 2007 )
[1] => Array ( [0] => 2008 )
[2] => Array ( [0] => 2009 )
...
)
and this plusMinus one:
Array ( [0] => Array ( [plus] => 2 [date] => 2007 )
[1] => Array ( [minus] => 1 [date] => 2008 )
[2] => Array ( [minus] => 1 [date] => )
[3] => Array ( [plus] => 1 [date] => 2010 [minus] => 1 )
)
I have been trying to combine them into this:
Array ( [0] => Array ( [date] => 2007 [plus]=> 2)
[1] => Array ( [date] => 2008 [minus]=> 1)
[2] => Array ( [date] => 2009 [plusMinus]=> 0)
[3] => Array ( [date] => 2010 [plus] => 1 [minus]=>1 )
...
)
So basically I want to check if a value of the date array exists in the plusMinus array. If true the date and values from the plusMinus array shall replace the entry in the date array.
If false, the original date array entry is complemented by a [plusMinus] => 0 key-value pair.
The way I have tried to do it is this:
foreach ($filler as $key1 => $value1)
{
foreach ($plusMinus as $key2 => $value2)
{
if ($value1['0'] !== $value2['date'])
{
$value1['plusMinus'] = '0';
$result2[$key1][] = $value1;
}
elseif ($value1['0'] == $value2['date'])
{
if (array_key_exists('plus',$value2))
{
$value1['plus'] = $value2['plus'];
$result2[$key1][]=$value1;
}
elseif(array_key_exists('minus',$value2))
{
$value1['minus'] = $value2['minus'];
$result2[$key1][]=$value1;
}
elseif(array_key_exists('minus',$value2) &&
array_key_exists('plus',$value2))
{
}
}
}
}
$valuesComplete = array();
foreach ($result2 as $value) {
$result2 = $value['0'];
array_push($valuesIncomplete, $result2);
}
return $valuesComplete;
Instead of the desired outcome described above I get this:
Array ( [0] => Array
( [0] => 2007 [plus] => 2 )
[1] => Array ( [0] => 2008 [plusMinus => 0 )
[2] => Array ( [0] => 2009 [plusMinus] => 0 )
[3] => Array ( [0] => 2010 [plusMinus] => 0 )
[4] => Array ( [0] => 2011 [plusMinus] => 0 )
[5] => Array ( [0] => 2012 [plusMinus] => 0 )
[6] => Array ( [0] => 2013 [plusMinus] => 0 )
)
What am I missing? Thanks for any help!
Unfortunately, because of the input data format, I can't see any way to do this that doesn't involve an O(n + m + p) operation. But no matter, you gotta do what you gotta do.
Firstly I would start by filtering the useless elements from the PlusMinus array. Since it's already fairly close to the desired output format, it makes sense to use this as the base of the result.
$temp = array();
foreach ($plusMinus as $item) {
if (!empty($item['date'])) {
$temp[$item['date']] = $item;
}
}
Notice that I used the date as the index of the temporary array we're using to build the result. This is to allow you to easily ensure that the result array is in the correct order, and to quickly check whether an item needs to be added from the Filler array.
Next, we need to add any missing elements from the Filler array:
foreach ($filler as $item) {
if (!isset($temp[$item[0]])) {
$temp[$item[0]] = array(
'date' => $item[0],
'plusMinus' => 0
);
}
}
Now all the data is in the array in the correct format, we just need to sort it:
ksort($temp);
...and get convert it back to an indexed array:
return array_values($temp);
No need for the performance killing nested loops or complex flow control.
See it working
As I understood you need to add years that not in second array but in first?
In that case you can do:
foreach ($filler as $key1 => $value1)
{
$ok = false;
foreach ($plusMinus as $key2 => $value2)
{
if($value2['date']==$value1[0])
{
$ok = true;
break;
}
}
if(!$ok)
{
$plusMinus[$value1[0]]=array('date'=>$value1[0], 'plusMinus'=>0);
}
}
<?php
$a1 = array(array( 2007 ),
array( 2008 )
);
$a2 = array(array('plus'=>1, 'date'=>2007),
array('minus'=>1,'date'=>2008),
array('plus'=>1, 'minus'=>1, 'date'=>2008)
);
$r = array();
foreach($a1 as $k1=>$d1) {
$year = $d1[0];
foreach( $a2 as $k2=>$d2 ) {
if( $d2['date'] == $year ) {
$r[$year]['date'] = $year;
if(isset($d2['plus'])) {
$r[$year]['plus'] = $d2['plus'];
}
if(isset($d2['minus'])) {
$r[$year]['minus'] = $d2['minus'];
}
}
}
}
print_r($r);
and result
Array
(
[2007] => Array
(
[date] => 2007
[plus] => 1
)
[2008] => Array
(
[date] => 2008
[minus] => 1
[plus] => 1
)
)
$ar1 = array( array(2007), array(2008), array(2009), array(2010) );
$ar2 = array(
array("date"=>2007, "plus"=>2),
array("date"=>2008, "minus"=>1),
array("date"=>"", "minus"=>1),
array("date"=>2010, "plus"=>1, "minus"=>1)
);
foreach($ar2 as $key=>$val){
if(isset($ar1[$key][0]))
$val["date"] = $ar1[$key][0];
$ar2[$key] = $val;
}
I am not sure if I understand you correctly but this works fine...
It will work only if you are sure that your both arrays "date" equals one to other..
This is what I came up with:
To not create the product of both arrays (foreach inside foreach), I first index the $plusMinus array with the date. That will allow to test quickly if a year exists or not:
$years = array_combine(array_column($plusMinus, 'date'), $plusMinus);
This uses the array_column() function of PHP 5.5, if you don't have it you can easily create it your own.
After doing that it is exactly how you wrote it in your own words:
foreach($date as &$entry)
{
list($year) = $entry;
$entry = array('date' => $year);
// check if a value of the date array exists in the plusMinus array.
if (isset($years[$year])) {
// If true the date and values from the plusMinus array shall replace the entry in the date array
$entry += $years[$year];
} else {
// If false, the original date array entry is complemented by a [plusMinus] => 0 key-value pair.
$entry += array('plusMinus' => 0);
}
}
unset($entry);
See it i action.
This will work just fine.
I did not at all understand your question, but if i got it this is the way:
First make your $datearray more understandable like this:
$dateArray = array(2007,2008,2009,2010);
$plusMinus = array(
array( 'plus' => 2 ,'date' => 2007),
array( 'minus' => 1 ,'date' => 2008),
array ( 'minus' => 1 , 'date' => '' ),
array ( 'plus' => 1 , 'date' => 2010 , 'minus' => 1 )
);
You can make it multidimensional later;
After that:
foreach($dateArray as $k=>$v)
{
if(in_array($v,$plusMinus[$k]))
{
$filler[$k] = $plusMinus[$k];
}
else{
if(empty($plusMinus[$k]['date']))
{
$filler[$k]['date']= $v;
$filler[$k]['plusMinus'] = 0;
}
}
}
This is simple and clean, understandable way with very little code if your arrays will always have the structure you described, meaning the plusMinus values for 2007 are in the cell [0] and the 2007 in the dateArrays is also in the cell [0] like you have shown. I hope i could help.

Need help to understand result set from PDO

I have the following function executing PDO queries:
// removed error handling for presenting here
function getRows($sql) {
$stmt = $this->db->query($sql);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
}
The result is:
Array
(
[0] => Array
(
[id] => 1
[category] => Audi
)
[1] => Array
(
[id] => 2
[category] => BMW
)
[2] => Array
(
[id] => 3
[category] => Chrysler
)
)
The the following foreach code:
foreach($result as $key => $value ) {
echo $value.'<br/>';
}
outputs this:
Array
Array
Array
What can I do so it returns the following?
Audi
BMW
Chrysler
I understand that I could just do $value['category].
But that's not what I want to achieve / understand. I would like the resultset not to be an array of arrays.
try
foreach($result as $key => $value ) {
echo $value['category'].'<br/>';
}
Alternative
foreach($result as $k)
{
echo $k['category'];
}
The foreach loop splits up your array into key, value pairs. The key in your loop is the index of the array, the value is an array containing ID and Category.
To access the category simply do:
foreach($result as $key => $value ) {
echo $value['category'].'<br/>';
}

Categories