foreach loop in array value in only last value print - php

I have get foreach loop in month and total month value count data in array print but only last value print in array
foreach($rawData as $Data)
{
$monthsss = $Data['month_no'];
if($monthsss=='1')
{
$arrayF['jan'] = $Data['month_count'];
}
else
{
$arrayF['jan'] = '0';
}
if($monthsss=='2')
{
$arrayF['feb'] = $Data['month_count'];
}
else
{
$arrayF['feb'] = '0';
}
}

When someone comments and asks Please show input and expected output. this is not done to give you more work, but there are many ways to achieve what you want but many answers can be wrong or require much more code (as with the accepted answer).
Presuming this is your data:
$rawData = [
['month_no' => 1, 'month_count' => 1],
['month_no' => 2, 'month_count' => 1],
['month_no' => 3, 'month_count' => 1],
['month_no' => 4, 'month_count' => 1],
['month_no' => 1, 'month_count' => 2],
['month_no' => 6, 'month_count' => 2],
['month_no' => 7, 'month_count' => 6],
['month_no' => 12, 'month_count' => 4],
];
Do you want just the summed up values?
<?php
$array = [];
foreach ($rawData as $data) {
$m = strtolower(DateTime::createFromFormat('!m', $data['month_no'])->format('M'));
$array[$m] = !isset($array[$m]) ? $data['month_count'] : $array[$m]+$data['month_count'];
}
print_r($array);
https://3v4l.org/vXgCL
Array
(
[jan] => 3
[feb] => 1
[mar] => 1
[apr] => 1
[jun] => 2
[jul] => 6
[dec] => 4
)
Or do you want an array of all the months with the summed up values:
<?php
$array = [];
foreach (range(1, 12) as $month) {
$m = strtolower(DateTime::createFromFormat('!m', $month)->format('M'));
$monthSet = array_filter($rawData, function ($v) use ($month) {
return $v['month_no'] === $month;
});
$array[$m] = 0;
foreach ($monthSet as $data) {
$array[$m] += $data['month_count'];
}
}
print_r($array);
https://3v4l.org/vqnnv
Array
(
[jan] => 3
[feb] => 1
[mar] => 1
[apr] => 1
[may] => 0
[jun] => 2
[jul] => 6
[aug] => 0
[sep] => 0
[oct] => 0
[nov] => 0
[dec] => 4
)
Or perhaps don't even care about the month's strings as your comment suggests.
<?php
$array = [];
foreach ($rawData as $data) {
$m = $data['month_no'];
$array[$m] = !isset($array[$m]) ? $data['month_count'] : $array[$m]+$data['month_count'];
}
print_r($array);
https://3v4l.org/7gKRo
Array
(
[1] => 3
[2] => 1
[3] => 1
[4] => 1
[6] => 2
[7] => 6
[12] => 4
)
Its why we ask..

Please modify your code as follows
foreach($rawData as $Data)
{
$monthsss = $Data['month_no'];
if($monthsss=='1')
{
$arrayF['jan'] = is_null($Data['month_count'])? 0 : $Data['month_count'];
}
if($monthsss=='2')
{
$arrayF['feb'] = is_null($Data['month_count'])? 0 : $Data['month_count'];
}
}

Related

How to subtract all column values in multi-dimensional array in Php?

How can I subtract all the columns values? My array is like
Array
(
[0] => Array
(
[id] => 1
[web_traffic] => 442
[form_users] => 131
[date] => 20181004
)
[1] => Array
(
[id] => 2
[web_traffic] => 102
[form_users] => 15
[date] => 20181003
)
[2] => Array
(
[id] => 3
[web_traffic] => 387
[form_users] => 97
[date] => 20181002
)
)
I need to subtract the each column(except date & id) and get the result based on date(Ascending order). For example 20181004 means 4th October 2018. My output should like the below
Array
(
[web_traffic] => -152
[form_users] => -49
)
My code took reference from How to sum all column values in multi-dimensional array?
foreach ($data as $value) {
unset($value[ 'id' ]);
$time = date('Ymd', strtotime($value[ 'date' ]));
if (in_array($time, $dates)) {
$value[ 'date' ] = $time;
foreach ($value as $key => $secondValue) {
if ( !isset($output[ $key ])) {
$output[ $key ] = 0;
}
$output[ $key ] -= $secondValue;
}
}
}
Use PHP array_reduce() and array_column() like this:
$initial_array = array(array('id' => 1,
'web_traffic' => 442,
'form_users' => 131,
'date' => 20181004),
array('id' => 2,
'web_traffic' => 102,
'form_users' => 15,
'date' => 20181003),
array('id' => 3,
'web_traffic' => 387,
'form_users' => 97,
'date' => 20181002));
function sum($carry, $item)
{
$carry -= $item;
return $carry;
}
$web_traffic = array_column($initial_array, "web_traffic");
$form_users = array_column($initial_array, "form_users");
$date = array_column($initial_array, "date");
array_multisort($date, SORT_ASC, $form_users, SORT_DESC, $initial_array);
$result_array = Array(
"web_traffic" => array_reduce(array_column($initial_array, "web_traffic"), "sum",2*$initial_array[0]['web_traffic']),
"form_users" => array_reduce(array_column($initial_array, "form_users"), "sum",2*$initial_array[0]['form_users'])
);
print_r($result_array);
I would first sort the array using usort() in example.
Sorting first, because that can be tricky to substract in 1 loop the oldest datas to the newers one.
Separating intentions provide a cleaner code, easier to maintain.
The dates don't need to be converted into a date. The string is well formatted and can be used as is in a comparison and a sort. "20170101" < "20180101", "20180101" < "20181001" and "20181002" < "20181004"
When done, I'll save the first values as initial values to be used in substract.
Then, loop the sorted array and substract the 'web_traffic' and 'form_users' to the initial values.
$datas = array(array('id' => 1,
'web_traffic' => 442,
'form_users' => 131,
'date' => 20181004),
array('id' => 2,
'web_traffic' => 102,
'form_users' => 15,
'date' => 20181003),
array('id' => 3,
'web_traffic' => 387,
'form_users' => 97,
'date' => 20181002));
//If needed, you can backup the original array, because usort() will modify it.
$backUpDatas = $datas;
//Sort
usort($datas, function ($arr1, $arr2)
{
if (isset($arr1['date']) && isset($arr2['date']))
{
if ($arr1['date'] == $arr2['date'])
return (0);
return (($arr1['id'] > $arr2['id']) ? (-1) : (1));
}
});
//Initial values
$finalValues['web_traffic'] = $datas[0]['web_traffic'];
$finalValues['form_users'] = $datas[0]['form_users'];
//Substract
foreach ($datas as $key => $value)
{
if ($key > 0)
{
if (isset($value['web_traffic']))
$finalValues['web_traffic'] -= $value['web_traffic'];
if (isset($value['form_users']))
$finalValues['form_users'] -= $value['form_users'];
}
}
var_dump($finalValues);
Output :
array (size=2)
'web_traffic' => int -157
'form_users' => int -49

replace a foreach loop with a functional programming approach

Below is an example of a function that adds a constant number to the keys of an array -
function addConstantToArrayKeys($seed_array, $constant)
{
foreach($seed_array as $key => $value){
$a[$key + $constant] = $value;
}
return $a;
}
$basearray = [1 => 17, 2 => 24, 3 => 12];
$test = addConstantToArrayKeys($basearray, 19);
The result of this example is:
Array
(
[1] => 17
[2] => 24
[3] => 12
)
Array
(
[20] => 17
[21] => 24
[22] => 12
)
It works as desired but can this method be rewritten somehow using a functional programming approach that can achieve the same result?
I have tried this:
function addConstantToArrayKeys($seed_array, $constant)
{
return array_map(function($key, $element) use($constant)
{return $a[$key + $constant] = $element;},
array_keys($seed_array), array_values($seed_array));
}
But it does not handle the keys as desired. Here is the output -
Array
(
[1] => 17
[2] => 24
[3] => 12
)
Array
(
[0] => 17
[1] => 24
[2] => 12
)
Edit -
Thanks to Progrock's answer, this worked -
function addConstantToArrayKeys($seed_array, $constant)
{
return array_combine(array_map(
function($key) use($constant) {
return $key + $constant;
}, array_keys($seed_array)), $seed_array);
}
May be its too late but this should work for you as you wanted the functional approach.
function addConstantToArrayKeys($basearray, $constant){
$arrayReindexed = [];
array_walk($basearray,function($v,$k) use (&$arrayReindexed, $constant) {
$key = $k;
$k = $key + $constant;
$arrayReindexed[$k] = $v;
});
return $arrayReindexed;
}
$basearray = [1 => 17, 2 => 24, 3 => 12];
$test = addConstantToArrayKeys($basearray, 19);
print '<pre>';
print_r($test);
print '</pre>';
Output:
Array (
[20] => 17
[21] => 24
[22] => 12
)
You could use something unreadable like this. It does not mutate existing array keys.
<?php
$nums = [
1 => 17,
2 => 24,
3 => 12
];
$out = array_combine(array_map(
function($int) {
return $int + 10;
}, array_keys($nums)), $nums);
var_export($out);
Output:
array (
11 => 17,
12 => 24,
13 => 12,
)
Your first example is perfectly functional and readable, but for the naming.
<?php
$nums = [
1 => 17,
2 => 24,
3 => 12
];
$add_num_to_keys = function (array $in, $num) {
$out = [];
foreach($in as $k => $v)
$out[$k + $num] = $v;
return $out;
};
$out = $add_num_to_keys($nums, 10);
var_export($out);
Output:
array (
11 => 17,
12 => 24,
13 => 12,
)
You can't do:
foreach($in as &$k => $v)
$k += 10;
As the key element can't be a reference.

Get previous and next array by key from array object

i have array object and want get 2 previous and and 2 next array group by specific key.
Array
(
[467] => stdClass Object
(
[id] => 467
[user_id] => 1
)
[468] => stdClass Object
(
[id] => 468
[user_id] => 1
)
[469] => stdClass Object
(
[id] => 469
[user_id] => 1
)
[474] => stdClass Object
(
[id] => 474
[user_id] => 1
)
[475] => stdClass Object
(
[id] => 475
[user_id] => 1
)
[479] => stdClass Object
(
[id] => 479
[user_id] => 1
)
[480] => stdClass Object
(
[id] => 480
[user_id] => 1
)
)
If key define 474 will result:
Previous array group from key 469 and 468
Next array group from key 475 and 479
If don't have previous and next array, i want no result
I try this method, but not working.
$val = 474;
$currentKey = array_search($val, $array);
$before = (isset($array[$currentKey - 2])) ? $array[$currentKey - 2] :
$after = (isset($array[$currentKey + 2])) ? $array[$currentKey + 2] : $array[0];
var_dump($before, $after);
Please help.
What my method will do is, search for the $key value and return its offset in the array. You were using array_search() on the input array's values, so that's where it fell flat.
Then if the offset value is not false, I attempts to slice the 5 desired subarrays from the input array. If it doesn't return 5, then it fails.
The second code will not trigger a failure if the collection of subarrays is less than 5.
Code: (Demo)
$array=[
467=>(object)['id'=>467,'user_id'=>1],
468=>(object)['id'=>468,'user_id'=>1],
469=>(object)['id'=>469,'user_id'=>1],
474=>(object)['id'=>474,'user_id'=>1],
475=>(object)['id'=>475,'user_id'=>1],
479=>(object)['id'=>479,'user_id'=>1],
480=>(object)['id'=>480,'user_id'=>1]
];
$key=480;
// require 5 subarrays or none:
if(($offset=array_search($key,array_keys($array)))<2 || sizeof($result=array_slice($array,$offset-2,5))!=5){
echo "Fail";
}else{
var_export($result);
}
echo "\n---\n";
// allow any number of subarrays up to 5:
if(($offset=array_search($key,array_keys($array)))===false){
echo "Fail";
}else{
// adjust $offset and $length values to handle array "overflow"
if($offset<2){
$length=$offset+3;
}elseif(($diff=sizeof($array)-$offset)<3){
$length=$diff+2;
}else{
$length=5;
}
$offset=max(0,$offset-2);
var_export(array_slice($array,$offset,$length));
}
Output:
Fail
---
array (
0 =>
stdClass::__set_state(array(
'id' => 475,
'user_id' => 1,
)),
1 =>
stdClass::__set_state(array(
'id' => 479,
'user_id' => 1,
)),
2 =>
stdClass::__set_state(array(
'id' => 480,
'user_id' => 1,
)),
)
Here is a visual representation and some more explanation of what the second method is doing:
The following explanation uses a 6-element array to demonstrate the calculations.
I = 'elements labeled by their indices'
S = 'the slice'
T = 'target index'
L = 'length of slice'
I ST ST ST ST ST ST When $target index is:
0 ╗0 ╗ ╗ 0, then $offset=0 and $length=3
1 ║ ║1 ║ ╗ 1, then $offset=0 and $length=4
2 ╝ ║ ║2 ║ ╗ 2, then $offset=0 and $length=5
3 ╝ ║ ║3 ║ ╗ 3, then $offset=1 and $length=5
4 ╝ ║ ║4 ║ 4, then $offset=2 and $length=4
5 ╝ ╝ ╝5 5, then $offset=3 and $length=3
L: 3 4 5 5 4 3
Since your array is not in the sequence, try this one Demo.
$arr = array( 467 => (object) ['id' => 467, 'user_id' => 1],
468 => (object) ['id' => 468, 'user_id' => 1],
469 => (object) ['id' => 469, 'user_id' => 1],
474 => (object) ['id' => 474, 'user_id' => 1],
475 => (object) ['id' => 475, 'user_id' => 1],
479 => (object) ['id' => 479, 'user_id' => 1],
480 => (object) ['id' => 480, 'user_id' => 1],);
$find = 474;
$before2 = $before1 = $next1 = $next2 = array();
$flag = false;
foreach ($arr as $key => $val) {
if($key == $find) {
$flag = true;
}
if(!$flag) {
if(!empty($before1)){
$before2 = $before1;
}
$before1 = $val;
}
if($key != $find) {
if($flag && empty($next2)){
if(!empty($next1)){
$next2 = $next1;
}
$next1 = $val;
}
if(!empty($next2)){
break;
}
}
}
if($flag) {
echo "matching values =>";
var_dump($before2);
var_dump($before1);
var_dump($next1);
var_dump($next2);
} else {
echo "given index not found!";
}

get max and min value each column in multdimensional array php

I have a multidimensional array
$array1 = array(
0 => array(34554, 45, 4545454),
1 => array(434534, 35, 345345),
2 => array(43534, 35, 4343445),
3 => array(35534, 34, 342323)
);
Can we find the minimum and maximum value for each value? if we want to find min for first and second column, the other column is max, and the result array is
$array2 = array(
0=>34554,
1=>34,
2=>4545454
);
i've tried this to get min
$result = array(); // save result
array_walk_recursive($ary, function($v, $k) use (&$result) {
if (!isset($result[$k])) $result[$k] = $v;
elseif ($result[$k] > $v) $result[$k] = $v;
});
print_r ($result);
and tried this to get max
$result = array(); // save result
array_walk_recursive($ary, function($v, $k) use (&$result) {
if (!isset($result[$k])) $result[$k] = $v;
elseif ($result[$k] < $v) $result[$k] = $v;
});
print_r ($result);
Thank you.
try below solution:
$array1 = array(
0 => array(34554, 45, 4545454),
1 => array(434534, 35, 345345),
2 => array(43534, 35, 4343445),
3 => array(35534, 34, 342323)
);
//max values
$max_arr = array_map(function ($val) {
return max($val);
}, $array1);
print_r($max_arr);
//min values
$min_arr = array_map(function ($val) {
return min($val);
}, $array1);
print_r($min_arr);
//min and max values
$min_max_arr = array_map(function ($val) {
return array('min' => min($val), 'max' => max($val));
}, $array1);
print_r($min_max_arr);
output:
//max values
Array
(
[0] => 4545454
[1] => 434534
[2] => 4343445
[3] => 342323
)
//min values
Array
(
[0] => 45
[1] => 35
[2] => 35
[3] => 34
)
//min and max values
Array
(
[0] => Array
(
[min] => 45
[max] => 4545454
)
[1] => Array
(
[min] => 35
[max] => 434534
)
[2] => Array
(
[min] => 35
[max] => 4343445
)
[3] => Array
(
[min] => 34
[max] => 342323
)
)
I have added some more element so that you can notice how it works, I have arranged max min as key and value pair, if you will edit your question and show me what you want as output, I will update it.
<?php
$array1 = array(
0 => array(34554, 45, 4545454),
1 => array(434534, 35, 345345),
2 => array(43534, 35, 4343445),
3 => array(9355434, 34, 342323),
4 => array(35534, 34, 342323),
5 => array(8544534, 34, 342323),
6 => array(35534, 34, 342323)
);
foreach($array1 as $arr1){
$max = max($arr1);
$arr[$max] = min($arr1);
}
var_dump($arr);
output
array (size=6)
4545454 => int 45
434534 => int 35
4343445 => int 35
9355434 => int 34
342323 => int 34
8544534 => int 34

Sorting an array via user defined function

I want a user defined function for sorting a multi dimension array:
<?php
$arr1 = array(
49,
8,
array(
'Muazam',
'Ali',
'Rana',
'Amina',
'Surya',
'Danish',
'Raina',
4,
3,
2,
1,
) ,
7,
6,
5,
4,
3,
2,
1,
0,
);
function abc($arr)
{
$len = count($arr) - 2;
foreach($arr as $key => $value)
{
for ($a = 0; $a <= $len; $a++)
{
if ($arr[$a] > $arr[$a + 1])
{
$temp4 = $arr[$a];
$arr[$a] = $arr[$a + 1];
$arr[$a + 1] = $temp4;
}
}
if (is_array($value))
{
abc($value, $a = $a + 1);
}
}
} //2nd foreach close
echo "<pre>";
print_r($arr);
echo "</pre>";
}
This is a basic usage of a recursive function:
$arr1 = array(49, 8, array(
'Muazam', 'Ali', 'Rana', 'Amina', 'Surya', 'Danish', 'Raina', 4, 3, 2, 1,
), 7, 6, 5, 4, 3, 2, 1, 0);
function recursiveSort(&$array)
{
foreach ($array as &$value) {
if (is_array($value)) {
recursiveSort($value);
}
}
return sort($array);
}
recursiveSort($arr1);
echo '<pre>';
print_r($arr1);
echo '</pre>';
The result would be:
Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 3
[4] => 4
[5] => 5
[6] => 6
[7] => 7
[8] => 8
[9] => 49
[10] => Array
(
[0] => Ali
[1] => Amina
[2] => Danish
[3] => Muazam
[4] => Raina
[5] => Rana
[6] => Surya
[7] => 1
[8] => 2
[9] => 3
[10] => 4
)
)
Here Is Answer.. Sorting a multi dimensional array without using built in function.
$arr1 = array(1,3,5,'2',array(99,55,array(111,444,array('a','r','p','e','t'),777),66,99),8,9,0,3,1);
function abc(&$arr)
{
$len=count($arr)-2;
foreach($arr as $key => &$value)
{
for ($a=0;$a<=$len;$a++){
if($arr[$a]>$arr[$a+1])
{
$temp4=$arr[$a];
$arr[$a]=$arr[$a+1];
$arr[$a+1]=$temp4;
}
}
if(is_array($value))
{
abc($value,$a=$a+1);
}
}//foreach close
//}//2nd foreach close
echo "<pre>";
return $arr;
echo "</pre>";
}//function close
print_r (abc($arr1));

Categories