PHP compare previous values and store latest value in array - php

Following is my code to bring all the latest dates in a month from dates array
$dates = Array
(
"2017/03/05",
"2017/03/06",
"2017/04/01",
"2017/04/16",
"2017/06/16",
"2017/06/19",
"2017/07/07",
"2017/08/19",
);
$curr_val = '';
$years = Array();
$months = Array();
foreach($dates as $d) {
list($y,$m) = explode("/",$d);
$years[$y][] = $d;
if ($m != $curr_val){
$months[$y."/".$m][] = $d;
$curr_val = $m ;
}
}
$years = array_values($years);
$months = array_values($months);
print_r($months);
Above code is printing values of first occurance date in a month. But i want the latest date from month.
Above code gives following output
Array ( [0] => Array ( [0] => 2017/03/05 ) [1] => Array ( [0] => 2017/04/01 ) [2] => Array ( [0] => 2017/06/16 ) [3] => Array ( [0] => 2017/07/07 ) [4] => Array ( [0] => 2017/08/19 ) )
But expected code is
Array ( [0] => Array ( [0] => 2017/03/06 ) [1] => Array ( [0] => 2017/04/16 ) [2] => Array ( [0] => 2017/06/19 ) [3] => Array ( [0] => 2017/07/07 ) [4] => Array ( [0] => 2017/08/19 ) )
Instead of printing first date in month, i want last date of month to be printed. how can i get that??

Your code could be reduced a lot. Here's what I could do:
$dates = Array
(
"2017/03/05",
"2017/03/06",
"2017/04/01",
"2017/04/16",
"2017/06/16",
"2017/06/19",
"2017/07/07",
"2017/08/19",
);
$array = [];
foreach($dates as $d) {
$date = \DateTime::createFromFormat('Y/m/d' , $d);
if (
!isset($array[$date->format('Y')][$date->format('m')])
|| $array[$date->format('Y')][$date->format('m')] < $date
) {
$array[$date->format('Y')][$date->format('m')] = $date;
}
}
print_r($array);
It's a simple logic that will check if the value is higher inside the same year/month and replace if it is.
Result:
Array (
[2017] => Array
(
[03] => DateTime Object
(
[date] => 2017-03-06 22:18:42.000000
[timezone_type] => 3
[timezone] => Europe/Amsterdam
)
[04] => DateTime Object
(
[date] => 2017-04-16 22:18:42.000000
[timezone_type] => 3
[timezone] => Europe/Amsterdam
)
[06] => DateTime Object
(
[date] => 2017-06-19 22:18:42.000000
[timezone_type] => 3
[timezone] => Europe/Amsterdam
)
[07] => DateTime Object
(
[date] => 2017-07-07 22:18:42.000000
[timezone_type] => 3
[timezone] => Europe/Amsterdam
)
[08] => DateTime Object
(
[date] => 2017-08-19 22:18:42.000000
[timezone_type] => 3
[timezone] => Europe/Amsterdam
)
)
)

Like this:
foreach($dates as $d) {
list($y,$m) = explode("/",$d);
$years[$y][] = $d;
$months[$y."/".$m] = [$d];
}
Don't worry about keeping track of the current value. Just keep overwriting $months[$y."/".$m] as you go, and you'll end up with the last date for each month.
If you want to get the most recent date from each month, rather than just the last one in the input array, make sure $dates is sorted before you start the loop. Since they're in year/month/day format, a simple sort($dates); should work. (In the case of your example, $dates is already sorted so this won't make any difference.)

This seems simplest to me:
Code: (Demo)
$dates[
"2017/03/05",
"2017/03/06",
"2017/04/01",
"2017/04/16",
"2017/06/16",
"2017/06/19",
"2017/07/07",
"2017/08/19"
];
foreach($dates as $d){
$result[substr($d,0,7)]=$d; // extract unique key from values
}
$result=array_values($result); // reindex array
var_export($result);
Output:
array (
0 => '2017/03/06',
1 => '2017/04/16',
2 => '2017/06/19',
3 => '2017/07/07',
4 => '2017/08/19',
)

Related

I want to group My array according to week in php

$date = array('01-01-2019','02-01-2019','05-01-2019','22-01-2019','02-02-2019','03-02-2019','24-02-2019');
Above is my array, I want to group the dates according to week so I can show them properly in reports. So it will be like this:
Array
(
[31-12-2018/06-01-2019] => Array // this is based in calendar week
(
[0] => 01-01-2019
[1] => 02-01-2019
[2] => 05-01-2019
)
[21-01-2019/27-01-2019] => Array
(
[0] => 22-01-2019
)
[28-01-2019/03-02-2019] => Array
(
[0] => 02-02-2019
[1] => 03-02-2019
)
[18-02-2019/24-02-2019] => Array
(
[0] => 24-02-2019
)
)
this are based on calendar week from Monday to Sunday
This code will do what you want. It converts each date value to a DateTime object, finds the start and end of week for that date, and then pushes the value into a new array indexed by the start & end of week values:
$date = array('01-01-2019','02-01-2019','05-01-2019','22-01-2019','02-02-2019','03-02-2019','24-02-2019');
$dates = array();
foreach ($date as $d) {
$od = date_create_from_format('d-m-Y', $d);
// get start and end of this week
$sow = $od->sub(new DateInterval('P' . ($od->format('N') - 1). 'D'))->format('d-m-Y');
$eow = $od->add(new DateInterval('P6D'))->format('d-m-Y');
$dates["$sow/$eow"][] = $d;
}
print_r($dates);
Output:
Array (
[31-12-2018/06-01-2019] => Array (
[0] => 01-01-2019
[1] => 02-01-2019
[2] => 05-01-2019
)
[21-01-2019/27-01-2019] => Array (
[0] => 22-01-2019
)
[28-01-2019/03-02-2019] => Array (
[0] => 02-02-2019
[1] => 03-02-2019
)
[18-02-2019/24-02-2019] => Array (
[0] => 24-02-2019
)
)
Demo on 3v4l.org

Select first working day from multidimensional array

I have a multidimensional array as shown below. in the day's array, it has various days which has both working and non-working days. now I want to consider first type=" working" as the start_date.
could you help me. thanks
Array
(
[error] => 0
[data] => Array
(
[start_date] => 2018-03-11
[end_date] => 2018-03-21
[days] => Array
(
[0] => Array
(
[type] => non_working
[sub_type] => weekend
[sub_sub_type] =>
[date] => 2018-03-11
)
[1] => Array
(
[type] => working
[sub_type] =>
[sub_sub_type] =>
[full_date] => 2018-03-12
)
[2] => Array
(
[type] => working
[sub_type] =>
[sub_sub_type] =>
[full_date] => 2018-03-13
)
)
)
)
I've tries this as of now:
$i=0;
$var = array();
foreach($arr['data']['days'][$i] as $var) {
if($var['type'] == 'working') {
break;
}
}
Rework $arr['data']['days'][$i] to $arr['data']['days']:
$start = null;
foreach($arr['data']['days'] as $var) {
if($var['type'] == 'working') {
$start = $var['date'];
break;
}
}

PHP Sum multi-dimentional array date interval, for an employee clock

time is DateTime Object formatted as:
$time = $date->format("%H:%i:%s");
I'm trying to sum hours and group employees.
I have:
Array
(
[0] => Array
(
[employee] => 2
[time] => 00:0:17
)
[1] => Array
(
[employee] => 1
[time] => 00:0:4
)
[2] => Array
(
[employee] => 2
[time] => 02:0:0
)
[3] => Array
(
[employee] => 3
[time] => 02:0:0
)
[4] => Array
(
[employee] => 3
[time] => 01:0:0
)
)
And I need something like, grouped and sum:
Array
(
[0] => Array
(
[employee] => 2
[totalTime] => 02:0:17
)
[1] => Array
(
[employee] => 1
[totalTime] => 00:0:4
)
[2] => Array
(
[employee] => 3
[totalTime] => 03:0:0
)
)
Any thoughts? Maybe convert time to UNIX and manipulate from there?
Since you want something like like the desired output, perhaps this will do:
foreach($array as $value){
if(!isset($data[$value['employee']])){
$data[$value['employee']] = 0;
}
$parsed = date_parse($value['time']);
$data[$value['employee']] += $parsed['hour'] * 3600 + $parsed['minute'] * 60 + $parsed['second'];
}
print_r($data);
Instead of creating a multidimensional array, $data will have the key of the employee and the value of the total time in seconds.
Obviously you can convert seconds very easily to a format if you so please.

How to combine three arrays with [0] as key into one

How can i turn this array:
Array ( [0] => 80 ) Array ( [0] => 20 ) Array ( [0] => 90 )
Into such array:
Array (
[0] => 80,
[1] => 20,
[2] => 90
);
Code:
$percentage_result = $percentage_query->result_array(); //output below:
Output:
Array
(
[0] => Array
(
[id] => 62
[list_id] => 55
[start_date] => 1459987200
[end_date] => 1459987200
[percentage] => 80
)
[1] => Array
(
[id] => 64
[list_id] => 55
[start_date] => 1459814400
[end_date] => 1459814400
[percentage] => 20
)
[2] => Array
(
[id] => 63
[list_id] => 55
[start_date] => 1459900800
[end_date] => 1459900800
[percentage] => 90
)
I want to save all of the [percentage] and get the highest one.
Doing this:
$null = array();
foreach ($percentage_result as $ptime) {
//Days between start date and end date -> seasonal price
$start_time = $ptime['start_date'];
$end_time = $ptime['end_date'];
$percentage_sm = explode(',', $ptime['percentage']);
$mrg = array_merge($null, $percentage_sm);
print_r($mrg);
$msg shows me:
Array
(
[0] => 80
)
Array
(
[0] => 20
)
Array
(
[0] => 90
)
You can do this in very simple way like this
$percentage_sm = array(); //define blank array
foreach ($percentage_result as $ptime) {
//Days between start date and end date -> seasonal price
$start_time = $ptime['start_date'];
$end_time = $ptime['end_date'];
$percentage_sm[] = $ptime['percentage']; //assign every value to array
}
print_r($percentage_sm);
Use array_merge()
$result = array_merge($arr1, $arr2, $arr3);
print_r($result);
If you want to get the highest percentage value from your $percentage_result array, then the easiest way to do it is
$maxPercentage = max(array_column($percentage_result, 'percentage'));
rather than trying to do something weird with array_merge
(PHP >= 5.5.0)
If you're running a lower version of PHP, then you can do something similar with
$maxPercentage = max(
array_map(
$percentage_result,
function ($value) { return $value['percentage']; }
)
);

Duplicate php object into two similar objects

I have an object with some variables for events (id, date, time, etc) gathered from a database. Some events have multiple days per week, so I want to duplicate the event object for each day listed and mark which day it's being duplicated for.
For example, I have this object inside an array:
Array
(
[0] => stdClass Object
(
[id] => 1
[days] => Array
(
[0] => Mon
[1] => Tues
)
)
)
and I'd like it to look like this:
Array
(
[0] => stdClass Object
(
[id] => 1
[day] => Mon
[days] => Array
(
[0] => Mon
[1] => Tues
)
)
[1] => stdClass Object
(
[id] => 1
[day] => Tues
[days] => Array
(
[0] => Mon
[1] => Tues
)
)
)
For some reason, when it loops through the second time the object is getting updated in the 0 position of the main array and the 1 position like so:
Array
(
[0] => stdClass Object
(
[id] => 1
[day] => Tues
[days] => Array
(
[0] => Mon
[1] => Tues
)
)
[1] => stdClass Object
(
[id] => 1
[day] => Tues
[days] => Array
(
[0] => Mon
[1] => Tues
)
)
)
This is a replication of the array declaration and loop I'm using:
$out = array();
$arr = array();
$arr[0] = new stdClass();
$arr[0]->id = 1;
$arr[0]->days = array("Mon","Tues");
foreach($arr as $a){
foreach($a->days as $day){
$a->day = $day;
$out[] = $a;
}
}
I did the same thing with straight arrays (cast the object as an array) and there it worked as I hoped, but it'd be nice to know how to do it with objects as well.
Any ideas?
You've got a single object, $a, referenced from both spots in the array. To duplicate the object instead use $out[] = clone $a; in place of $out[] = $a;.

Categories