Is there a way that I can approach this to some other solution?
I have 7 arrays (monday, tuesday, wednesday, thrusday, friday, saturday, sunday).
Each one of this arrays have arrays inside of them. and I need to check if all days have the same amount of data.
So im comparinng something like this:
if(count($monday) == count($tuesday)){
if(count($tuesday) == count($wednesday)){
if(count($wednesday) == count($thursday)){
if(count($thursday) == count($fruday)){
if(count($fruday) == count($saturday)){
if(count($saturday) == count($sunday)){
echo 'ok whole week is the same';
}
else{
//print sunday
//compare the rest which could print and keep comparing rest of the days
}
}
else{
//print saturday and comapre
}
}
else{
//print friday and compare
}
}
else{
//print thurdasy and compare
}
}
else{
//print wednesday and compare
}
}
else{
//print tuesday and compare
}
}
else{
//print monday
//compare rest of the days
}
As you can see it would become a huge if statement tree, I dont have that much of experience to know any other approach to this, but id you do, please help me!
thank you!
Use $diff = array_diff($monday,$tuesday,$wednesday, etc...);
$diff will contain the differences if there are any...
$bol = 0;
if(count($monday) == count($tuesday)){
$bol = $bol+1
} else {print $moday;}
//continue for all weeks
if ($bol ==6) {
echo 'ok whole week is the same';
}
How about this:
<?php
echo "<pre>";
$days = array('sunday' => array(1,2), 'saturday' => array(1,2,3), 'friday' => array(1,2,3,5), 'thursday' => array(1,2,3), 'wednesday' => array(1,2,3,4,5,6), 'tuesday' => array(1), 'monday' => array(1,2, 3,4,5,6,7,8));
//Create a count array
$count = array();
//populate count array
foreach ($days as $k => $v)
{
$count[$k] = count($v);
}
//reverse sort it
arsort($count);
//if both end of array elements are the same all are the same
if (reset ($count) == end($count))
{
echo 'ok whole week is the same';
} else {
foreach ($count as $d => $c)
{
echo $d . ": " . implode ( ", " , $days[$d] ) . "\n";
}
}
echo "</pre>";
?>
Initial array of days:
Array
(
[sunday] => Array
(
[0] => 1
[1] => 2
)
[saturday] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[friday] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 5
)
[thursday] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[wednesday] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
)
[tuesday] => Array
(
[0] => 1
)
[monday] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 7
[7] => 8
)
)
and Output:
monday: 1, 2, 3, 4, 5, 6, 7, 8
wednesday: 1, 2, 3, 4, 5, 6
friday: 1, 2, 3, 5
thursday: 1, 2, 3
saturday: 1, 2, 3
sunday: 1, 2
tuesday: 1
This solution uses the fact that the two comparison variables are quite predictable (ie. a single day is compared with the very next day).
All the daily arrays are placed into a single weekly array, which is then looped over. If there is a discrepancy, the contents of the last variable are displayed and the loop continues.
If there are no discrepancies then the success message is displayed.
<?php
$bIsCorrect = true;
$weeks_array = array($monday,$tuesday,$wednesday,$thursday,$friday,$saturday,$sunday);
//Loop through weeks starting from $monday and going only to $saturday
for($i=0,$max_count=6; $i<$max_count; $i++) {
if(count($weeks_array[$i]) != count($weeks_array[$i+1])) {
$bIsCorrect = false;
$array_text = var_export($weeks_array[$i+1], true);
echo "Discrepancy : <br> $array_text";
echo "<hr>";
}
}
if($bIsCorrect) {
echo "ok whole week is the same";
}
Related
I have an array of time ranges like this:-
$events = array(
array("Monday", '19:00:00', '19:30:00', 0),
array("Monday", '19:10:00', '19:40:00', 0),
array("Tuesday", '19:10:00', '19:40:00', 0),
array("Wednesday", '19:10:00', '19:40:00', 0),
array("Monday", '19:30:00', '19:50:00', 0),
);
I am using bubble sort on the array:-
for($i = 0; $i < (count($events) - 1); $i++)
{
for($j = 1; $j < (count($events) - i - 1); $j++)
{
if($events[$i][0] < $events[$j][0])
{
if ($events[$j] > $events[($j + 1)])
{
$swap = $events[$j];
$events[$j] = $events[($j + 1)];
$events[($j + 1)] = $swap;
}
}
}
}
The result comes like this:-
Array (
[0] => Array (
[0] => Monday
[1] => 19:00:00
[2] => 19:30:00
[3] => 0)
[1] => Array (
[0] => Monday
[1] => 19:10:00
[2] => 19:40:00
[3] => 0)
[2] => Array (
[0] => Monday
[1] => 19:30:00
[2] => 19:50:00
[3] => 0)
[3] => Array (
[0] => Tuesday
[1] => 19:10:00
[2] => 19:40:00
[3] => 0)
[4] => Array (
[0] => Wednesday
[1] => 19:10:00
[2] => 19:40:00
[3] => 0)
)
Now I need to strike out those time ranges which overlap on a specific day.
Like this:
Array (
[0] => Array (
[0] => Monday
[1] => 19:00:00
[2] => 19:30:00
[3] => 1)
[1] => Array (
[0] => Monday
[1] => 19:10:00
[2] => 19:40:00
[3] => 1)
[2] => Array (
[0] => Monday
[1] => 19:30:00
[2] => 19:50:00
[3] => 1)
[3] => Array (
[0] => Tuesday
[1] => 19:10:00
[2] => 19:40:00
[3] => 0)
[4] => Array (
[0] => Wednesday
[1] => 19:10:00
[2] => 19:40:00
[3] => 0)
)
The ones which are [3] => 1, denote there is a time overlap conflict.
How can I proceed?
I tried to use this solution, but got no luck. Besides, mine has a day of week.
I had a little play and this is what I came up with. It preserves the original order of the $events array as textual days don't sort well (Friday would come before Wednesday etc). A bit brute force, not optimised or properly tested, but hope it's useful for ideas.
foreach ($events as $event_id=>$event) {
$days[$event[0]][]=[$event_id,$event[1],$event[2]];
}
foreach ($days as $dayevents) {
if (count($dayevents)>1) {
foreach ($dayevents as $dayevent1) {
foreach ($dayevents as $dayevent2) {
if ((($dayevent1[1]>$dayevent2[1]) and ($dayevent1[1]<$dayevent2[2])) or
(($dayevent1[2]>$dayevent2[1]) and ($dayevent1[2]<$dayevent2[2]))) {
$events[$dayevent1[0]][3]=1;
$events[$dayevent2[0]][3]=1;
}
}
}
}
}
$events = array(
array("Monday", '19:00:00', '19:30:00', 0),
array("Monday", '19:10:00', '19:40:00', 0),
array("Tuesday", '19:10:00', '19:40:00', 0),
array("Wednesday", '19:10:00', '19:40:00', 0),
array("Monday", '19:30:00', '19:50:00', 0),
);
$combined = array();
// first we collect all intervals for the given day
foreach($events as $record)
{
$combined[$record[0]][] = array(
$record[1], $record[2], 0
);
}
// then for each day we look if there are overlaps
foreach($combined as $day => &$intervals)
{
$len = count($intervals);
// we compare each interval with each of the rest intervals for the same day
foreach($intervals as $i => &$interval_1)
{
// we convert the start/end times of the interval A to an integer
$begin_1 = str_replace(':','',$interval_1[0]);
$end_1 = str_replace(':','',$interval_1[1]);
for($k = $i + 1; $k < $len; $k++)
{
// we convert the start/end times of the interval B to an integer
$begin_2 = str_replace(':','',$intervals[$k][0]);
$end_2 = str_replace(':','',$intervals[$k][1]);
// we compute the overlap of the 2 intervals
$overlap = max(0,$end_1 - $begin_1 - max(0,$end_1 - $end_2) - max(0,$begin_2 - $begin_1));
if($overlap)
{
$interval_1[2]++; // we increase the counter of interval A
$intervals[$k][2]++; // we increase the counter of interval B
}
}
}
}
<?php
$events = array(
array("Monday", '19:00:00', '19:10:00'),
array("Monday", '19:05:00', '19:20:00'),
array("Tuesday", '19:10:00', '19:40:00'),
array("Wednesday", '19:10:00', '19:40:00'),
array("Monday", '19:15:00', '19:30:00'),
);
function convertToSeconds($time){
$time = explode(":",$time);
return intval($time[0]) * 3600 + intval($time[1]) * 60 + intval($time[2]);
}
$time_ranges = [];
$hold_dates = [];
for($i=0;$i<=86401;++$i){
$time_ranges[] = 0;
$hold_dates[$i] = [];
}
$time_range_for_week = [];
$week_days = ['monday' ,'tuesday','wednesday','thursday','friday','saturday','sunday'];
foreach($week_days as $day){
$time_range_for_week[$day] = [
'hold_dates' => $hold_dates,
'time_range' => $time_ranges
];
}
foreach($events as &$data){
$start_time = convertToSeconds($data[1]);
$end_time = convertToSeconds($data[2]);
$time_range_for_week[strtolower($data[0])]['hold_dates'][$start_time][] = &$data;
$time_range_for_week[strtolower($data[0])]['hold_dates'][$end_time][] = &$data;
$time_range_for_week[strtolower($data[0])]['time_range'][$start_time] += 1;
$time_range_for_week[strtolower($data[0])]['time_range'][$end_time + 1] -= 1;
}
foreach($time_range_for_week as $day_name => &$day_data){
$sum = 0;
foreach($day_data['time_range'] as $time => $value){
$sum += $value;
if($sum > 1 && count($day_data['hold_dates'][$time]) > 0){
foreach($day_data['hold_dates'][$time] as &$each_event){
$each_event[3] = 1;
}
}
}
}
print_r($events);
Demo: https://3v4l.org/JeGdR
Algorithm:
This is rather simple and efficient than basic brute force.
To find out collisions between times, we first make an array of size 86400 for each day. 86400 because it is no. of seconds(24*60*60) for a day(like Monday or Tuesday etc).
The array looks like this for a particular day(like Monday or Tuesday etc):
Structure:
Array
(
[monday] => Array
(
[hold_dates] => Array
(
[],[],[],... till 86400
),
[time_range] => Array
(
[],[],[],... till 86400
),
),
[tuesday] => Array(
...
),
...
)
In the hold_dates key for a day, we are just going to have our array values at the start time and end times positions. Here start time is the 1st position(0-based indexing) in array("Monday", '19:10:00', '19:40:00', 0) and end time is 2nd position in array("Monday", '19:10:00', '19:40:00', 0). In the code, the lines look like:
Code:
$time_range_for_week[strtolower($data[0])]['hold_dates'][$start_time][] = &$data;
$time_range_for_week[strtolower($data[0])]['hold_dates'][$end_time][] = &$data;
The & is used for syncing updates with actual $events array, so it's a pass by reference.
The time_range will just hold integer values and those integer values as explained below.
Let's consider intervals like below:
[2,7],
[4,9],
[6,10]
We have a timeline like below:
1 2 3 4 5 6 7 8 9 10 11 // these are seconds from 1 to 11
+1 -1
+1 -1
+1 -1
1 1 2 2 3 3 2 2 1 0
In the above diagram, for each date's start time, we add +1, and -1 to it's end time + 1. This means that, when we iterate from 1 to 11 and keep summing values, if we find any date's start time or end time having a sum > 1, we found there is a collision and we need to set it's value to 1.
We do the same in the above code. Here, the space used for this code is 86400 * 7 = 604800, which is constant space O(1) since this does not depend upon size of $events.
Time complexity is again the constant iterations 86400 * 7 = 604800 + looping twice through each element in $events, which makes it O(n) where n is size of $events.
My question may sound abit silly, but I know it is possible to do. I'm actually trying to make the array from mysql to be different from the array I have shuffle it already. I want to maintain the array keys, just the value in different order.
Here is the example,
Array from MYSQL:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 7
[7] => 8
)
Array after shuffle:
Array
(
[0] => 3
[1] => 7
[2] => 8
[3] => 4
[4] => 1
[5] => 2
[6] => 5
[7] => 6
)
If you notice, MYSQL array key 3 has the same value as shuffle array, I want it to be different. How can I do so?
Here is my code:
function get_random_elements($array) {
$ori_array = $array;
echo "<pre>";
print_r($ori_array);
echo "</pre>";
shuffle($array);
echo "<pre>";
print_r($array);
echo "</pre>";
for($x=0; $x<count($array); $x++) {
if ($array[$x] == $ori_array[$x])
{
$dupliarray[] = "Array value: ".$array[$x]." Key :".$x;
unset($array[$x]);
}
}
echo "<pre>";
print_r($dupliarray);
echo "</pre>";
}
$mysql_array = array(0=>'1',1=>'2',2=>'3',3=>'4',4=>'5',5=>'6',6=>'7',7=>'8');
get_random_elements($mysql_array);
One solution can be to shuffle array until it became totally differ from source array:
$sourceArray = [0, 1, 2, 3, 4, 5, 6, 7, 8];
$shuffledArray = $sourceArray; //because function shuffle will change passed array
shuffle($shuffledArray);
while (count(array_intersect_assoc($sourceArray, $shuffledArray))) {
shuffle($shuffledArray);
}
echo '<pre>';
var_dump($sourceArray, $shuffledArray);
I suggest this variant: Code in sandbox
$startArray = [
0 => 1,
1 => 2,
2 => 3,
3 => 4,
4 => 5,
5 => 6,
6 => 7,
];
function getShuffledArray($startArray) {
$shuffledArray = [];
// save value of last element for situation when we have last 2 elements of start array and one of them - last
$lastElement = end($startArray);
while (count($startArray)) {
$candidateIndex = array_rand($startArray);
if ($candidateIndex == count($shuffledArray)) {
while ($candidateIndex == count($shuffledArray)) {
$candidateIndex = array_rand($startArray);
}
}
$shuffledArray[] = $startArray[$candidateIndex];
unset($startArray[$candidateIndex]);
// shuffle last two elements when one of them last (in start array)
if (count($startArray) == 2 && end($startArray) == $lastElement) {
$shuffledArray[] = end($startArray);
$shuffledArray[] = reset($startArray);
$startArray = [];
}
}
return $shuffledArray;
}
$shuffledArray = getShuffledArray($startArray);
print_r ($shuffledArray);
I'm having a lot of difficulty approaching a piece of code in PHP. I have an array of dates and values, for example
dates = (2014-12-01,2014-12-02,2014-12-08,2014-12-09,2014-12-10,2014-12-11)
values = (5,3,7,8,9,2)
You'll note that 12/01 is a Monday, as is 12/08. I'd like to form 4 arrays from these two arrays:
monday = (5,7)
tuesday = (3,8)
wednesday = (0,9)
thursday = (0,2)
You'll note that the arrays are formed by grabbing the values associated with the days of the week. However, in the case that a Wednesday date exists, for example, but the prior Tuesday does not, then the array should have a "0". In other words, the 4 arrays should all be the same length.
Can anyone help me write code in PHP to achieve this? Thanks in advance!
NOTE: So far, I have only determined how to find the day of the week from a date: date('l', strtotime("2014-12-08")); I really can't figure out the general algorithm to solve this.
$dates = array( '2014-12-01','2014-12-02','2014-12-08','2014-12-09',
'2014-12-10','2014-12-11' );
$values = array( 5, 3, 7, 8, 9, 2 );
$date = strtotime(min($dates));
$stop = strtotime(max($dates));
$dates = array_flip($dates);
$out = array();
while($date <= $stop)
{
$tmp = date('Y-m-d', $date);
$out[date('l', $date)][] = isset($dates[$tmp]) && isset($values[$dates[$tmp]]) ?
$values[$dates[$tmp]] : 0;
$date = strtotime('+1 day', $date);
}
print_r($out);
Result:
Array
(
[Monday] => Array
(
[0] => 5
[1] => 7
)
[Tuesday] => Array
(
[0] => 3
[1] => 8
)
[Wednesday] => Array
(
[0] => 0
[1] => 9
)
[Thursday] => Array
(
[0] => 0
[1] => 2
)
[Friday] => Array
(
[0] => 0
)
[Saturday] => Array
(
[0] => 0
)
[Sunday] => Array
(
[0] => 0
)
)
ps: how can I get the an array of all the dates included in the "dates" array associated with only all the Mondays?
Modify the code as, for example:
$tmp = date('Y-m-d', $date);
$exists = isset($dates[$tmp]) && isset($values[$dates[$tmp]]);
$out[date('l', $date)]['numbers'][] = $exists ? $values[$dates[$tmp]] : 0;
if ($exists) $out[date('l', $date)]['dates'][] = $tmp;
$date = strtotime('+1 day', $date);
You'll get an output as (example for monday)
[Monday] => Array
(
[numbers] => Array
(
[0] => 5
[1] => 7
)
[dates] => Array
(
[0] => 2014-12-01
[1] => 2014-12-08
)
)
Might be a better way to get the 0s in there without another loop but I'm headed out:
foreach($dates as $key => $val) {
$day = date('l', strtotime($val));
$result[$day][] = $values[$key];
}
foreach($result as &$val) {
if(count($val) == 1) {
array_unshift($val, 0);
}
}
print_r($result);
I am working with any multidimensional array Sorting when I need to sort the array with values and the values should be sorted according tot he date and time. How could I do that.
For Some situation I cant do that through Query I need to Sort through PHP Sort but the predefined function dosent help me.
My Array to be sorted:
Array
(
[events] => Array
(
[0] => Array
(
[0] => 213532
[1] => 100% View
[2] => 12/11/2014 09:00
[3] => 12/11/2014 11:00
)
[1] => Array
(
[0] => 213533
[1] => test 80
[2] => 12/11/2014 06:00
[3] => 12/11/2014 08:00
)
[2] => Array
(
[0] => 213534
[1] => wf4
[2] => 12/12/2014 00:00
[3] => 12/12/2014 23:59
)
[3] => Array
(
[0] => 213535
[1] => Standaard:
[2] => 12/12/2014 10:00
[3] => 12/12/2014 12:00
)
)
)
Every Sub Array of [2] Value.
['events'][$i][2]
Should be sorted and rearranged. in the following way.
12/11/2014 06:00
12/11/2014 09:00
12/12/2014 00:00
12/12/2014 10:00
How can I do that any logical help will be useful.
#Mario is right that usort is what you probably want. You can also use strtotime to convert the string date to an integer, which is easy to compare. I wrote up a working example here. You'll see that I first print out the data (not sorted), then call usort with my custom sort function. When I print out the array again, it's now in order by date.
function compare($a, $b) {
$timeA = strtotime($a[2]);
$timeB = strtotime($b[2]);
if ($timeA < $timeB) {
return -1;
}
if ($timeA > $timeB) {
return 1;
}
return 0;
}
function printArrayContents($arr) {
for ($i = 0; $i < count($arr); $i++) {
echo $arr[$i][2] , "<BR>";
}
}
$events = array(
0 => array(
0 => 213532,
1 => '100% View',
2 => '12/11/2014 09:00',
3 => '12/11/2014 11:00'
),
1 => array(
0 => 213533,
1 => 'test 80',
2 => '12/11/2014 06:00',
3 => '12/11/2014 08:00'
),
2 => array(
0 => 213534,
1 => 'wf4',
2 => '12/12/2014 00:00',
3 => '12/12/2014 23:59'
),
3 => array(
0 => 213535,
1 => 'Standaard:',
2 => '12/12/2014 10:00',
3 => '12/12/2014 12:00'
)
);
echo "Unsorted:<BR>";
printArrayContents($events);
if (usort($events, "compare")) {
echo "Sorted:<BR>";
printArrayContents($events);
} else {
echo "Sort failed.<BR>";
}
Output:
Unsorted:
12/11/2014 09:00
12/11/2014 06:00
12/12/2014 00:00
12/12/2014 10:00
Sorted:
12/11/2014 06:00
12/11/2014 09:00
12/12/2014 00:00
12/12/2014 10:00
What you're looking for is usort(), which allows you to define your own callback/comparison function.
Essentially you'll want something like this:
function my_event_sorter($left, $right) {
if ($left[2] == $right[2])
return 0;
return strtotime($left[2]) < strtotime($right[2]) ? -1 : 1;
}
usort($events, 'my_event_sorter');
This comparison function will receive two parameters (the two elements to be compared) and it's supposed to return one of three integer values:
-1: The left value is smaller than the right one (i.e. order is fine).
0: Both values are identical (i.e. order is fine as well).
1: The right value is smaller than the left one (i.e. order has to be swapped).
if they are unique, you can use the datetime values as a key and then use ksort:
$newArray = array();
foreach($events as $event){
$newArray[$event[2]] = $event;
}
ksort($newArray);
Sorry if the title of the question is unclear, I couldn't sum it up more precisely.
This is the issue:
To begin with, I have an array in this format:
Array (
[0] => 09:00
[1] => 10:00
[2] => 11:00
[3] => 12:00
[4] => 13:00
[5] => 14:00
[6] => 15:00
[7] => 16:00
[8] => 17:00
[9] => 18:00
)
Then some of the members are unset, so after that we're left with something like:
Array (
[0] => 09:00
[1] => 10:00
[6] => 15:00
[7] => 16:00
[8] => 17:00
[9] => 18:00
)
As you see, the array represents time slots. Now, what I need to do is eliminate all time slots shorter than 3 hours. So I need to go through the array and, wherever there are less than 3 members of the original array present, take them out too. So in the example above, since 09:00 and 10:00 are not followed by 11:00, I need to take them out and be left with:
Array (
[6] => 15:00
[7] => 16:00
[8] => 17:00
[9] => 18:00
)
How do I accomplish this? Logically, I think it might be easiest to check for 3 consecutive indexes, rather then checking the actual times but I'm open to any suggestions.
I've solved the problem on my own, and I made it generic so it would work for any duration, not just 3 hours.
$dur=3; //could be anything
foreach($work_times as $member){
$key=array_search($member,$work_times);
$a_ok=0;
for($options=0;$options<$dur;$options++){
$thisone=1;
for($try=$key-$options;$try<$key-$options+$dur;$try++){
if(!array_key_exists($try,$work_times))
$thisone=0;
}
if($thisone==1)
$a_ok=1;
}
if($a_ok==0)
unset($work_times[$key]);
}
$arr = array(
0 => '09:00',
1 => '10:00',
6 => '15:00',
7 => '16:00',
8 => '17:00',
9 => '18:00'
);
// for some testing
$arr += array(12 => '19:00', 13 => '20:00', 14 => '21:00');
$arr += array(16 => '22:00', 17 => '23:00');
$dontRemove = array();
foreach($arr as $key => $val) {
// if the next 2 keys are set
if (isset($arr[$key+1]) && isset($arr[$key+2])) {
$dontRemove[] = $key;
$dontRemove[] = $key+1;
$dontRemove[] = $key+2;
}
}
// combine and diff the keys to get the keys which should be actually removed
$remove = array_diff(array_keys($arr), array_unique($dontRemove));
foreach($remove as $key) {
unset($arr[$key]);
}
print_r($arr);
Try this:
<?php
function check() {
global $array;
$tmpArr = array_keys( $array );
$val1 = $tmpArr[0];
$val2 = $tmpArr[1];
$val3 = $tmpArr[2];
if( ( ++$val1 == $val2 ) && ( ++$val2 == $val3 ) ) {
// continuous
} else {
// not continuous, remove it
unset( $array[$tmpArr[0]] );
}
}
$array = array(
'0' => '09:00',
'1'=> '10:00',
'6' => '15:00',
'7'=> '16:00',
'8' => '17:00',
'9' => '18:00'
);
$total = count( $array );
$ctotal = 0;
while( $ctotal < $total ) {
if( count( $array ) <= 2 ) {
// this array has 2 elements left, which obviously
// nullifies the 3 continuous element check
$array = array();
break;
} else {
//check the array backwards
check();
$total--;
}
}
?>
Hope this helps
$a = Array(
0 => "09:00",
1 => "10:00",
6 => "15:00",
7 => "16:00",
8 => "17:00",
9 => "18:00",
11 => "20:00",
);
foreach ($a as $k => $v) {
// previous or next two time slots exist
$consecutive = (isset($a[$k-1]) or
(isset($a[$k+1]) and isset($a[$k+2])));
if (!$consecutive)
unset($a[$k]);
}