Grouping with hyphenate not working with i18N for weekdays - php

I am working on a snippet for displaying opening hours and it works fine in english language and when I change the keys of array to another language it doesn't hyphenate the letters instead it does separation by comma.
What am I doing Wrong?
Below is the PHP code with 2 arrays with 1 commented which is in english and which works fine. Another is an italian langugage weekdays
<?php
/*
// english weekdays
$openHours = array(
'Mon' => '9am-7pm',
'Tue' => '9am-7pm',
'Wed' => '9am-7pm',
'Thu' => '9am-10pm',
'Fri' => 'closed',
'Sat' => '9am-10pm',
'Sun' => '9am-10pm'
);
*/
// italian weekdays
$openHours = array(
'lunedì' => '9am-7pm',
'martedì' => '9am-7pm',
'mercoledì' => '9am-7pm',
'giovedì' => '9am-10pm',
'venerdì' => 'closed',
'sabato' => '9am-10pm',
'domenica' => '9am-10pm'
);
$new_array = array();
foreach($openHours as $key => $value)
{
if(in_array($value,$new_array))
{
$key_new = array_search($value, $new_array);//to get the key of element
unset($new_array[$key_new]); //remove the element
$key_new = $key_new.','.$key; //updating the key
$new_array[$key_new] = $value; //inserting new element to the key
}
else
{
$new_array[$key] = $value;
}
}
foreach ($new_array as $days=>$time){
$daylist = explode(',',$days);
if ($time!='closed'){
if (count($daylist)>2){
$limit = count($daylist)-1;
$first = $daylist[0];
$last = $daylist[$limit];
//loop will go here.
if (date('D', strtotime('+'.$limit.' days', strtotime($first)))==$last){
echo $first.'-'.$last.' '.$time.'<br>';
} else {
$sep = '';
foreach ($daylist as $sepdays){
echo $sep.$sepdays;
$sep = ',';
}
echo ' '.$time.'<br>';
}
} else {
echo $days.' '.$time.'<br>';
}
} else {
$daylist = explode(',',$days);
foreach ($daylist as $sepdays){
echo $sepdays.' '.$time.'<br>';
}
}
}
?>
RESULT
Current Result what am getting with italian language.
lunedì,martedì,mercoledì 9am-7pm
venerdì closed
giovedì,sabato,domenica 9am-10pm
Expected RESULT
This is what I'm expecting.
lunedì-mercoledì 9am-7pm
venerdì closed
giovedì,sabato,domenica 9am-10pm

You are using your array's keys within date and strtotime functions to do your comparisons, both functions works for English. If you need to do it on other languages you should use setlocale and strftime, it will be a lot more complicated process. My suggestions:
Use numeric representation of the days of the week (0-6) and on display, replace the number with the value for the desired language.
Use multidimensional arrays including the numeric day of the week and the opening hours.

Related

Group Array from .csv | PHP

I have this code and what i'm trying to do is , group the data coming from the .csv by Player , and then group by year and league , so for example , i will have faker -> 2021 -> lck->data ; ->2020->lck->data
and sometimes when a player has played more than one league in a year , faker->2021->lck->data | 2021->kespa->data
the problem is when i show the kills(image) , the year 2020 is adding the kills from 2021 plus kills from 2020.
and what i want is 2020 show the kills from that league and that year and the same with 2021.
The result im Getting :
Faker => 2021 => kills [1,2,3] ; 2020 => kills [1,2,3,6,9,12];
The expected result is :
Faker => 2021 => kills [1,2,3] ; 2020 => kills [6,9,12]
how can i achieve that ?
Thats the csv
gameid,datacompleteness,url,league,year,split,playoffs,date,game,patch,playerid,side,position,player,team,champion .....
thats my code;
<?php
$csvFileData = file('./datalck.csv');
$dataMatch = [];
foreach ($csvFileData as $lines) {
$data[] = str_getcsv($lines);
}
foreach ($dataMatch as $matchs) {
// So here i'm grouping the array by player
//[3] is the position for the league
//[4] is the position for year
//[13] is the position of player name ,
//[23] The position of kills
if ($matchs[13] != NULL and $matchs[13] != "") {
$group[$matchs[13]][] = [
'Player' => $matchs[13],
"kills" => $matchs[23],
'league' => $matchs[3],
'year' => $matchs[4],
];
}
}
foreach ($group as $players => $p) {
$kills = [];
foreach ($p as $op) {
$kills[] = $op['kills'];
$group2[$op['Player']][$op['year']][$op['league']] = [
"Player" => $op['Player'],
"kills" => $kills,
"league" => $op['league'],
"year" => $op['year'],
];
}
}
foreach ($group2 as $op2) {
echo '<pre>';
var_dump(($group2));
echo '</pre>';
}
?>
You are adding to $kills array, without taking care of the year.
So, when you parse the year 2021, the $kills array already contains the 2020 data.
You could create an empty array the first time (each new year), and then, fill it.
foreach ($group as $players => $p)
{
foreach ($p as $op)
{
// variables for readability
$plyr = $op['Player'];
$year = $op['year'];
$leag = $op['league'];
$kills = $op['kills'];
// create the initial state
if (!isset($group2[$plyr][$year][$leag]))
{
$group2[$plyr][$year][$leag] = [
"Player" => $plyr,
"league" => $leag,
"year" => $year,
"kills" => [], // empty array
];
}
// add value to array for the player/year/league :
$group2[$plyr][$year][$leag]['kills'][] = $kills;
}
}
See a working demo.

Create zero values for missing items in foreach loop

I have an application that extracts some information from mysql between two dates and returns an associative array. I am producing a graph with this information but have dates missing for the dates in the database that have no information to return. I cannot fix this on the mysql side as I only have read only access to the database.
My database method retrieves an associative array like the below:
[0] => Array
(
[number_of_calls] => 151
[total_call_time] => 00:01:30
[average_call] => 00:02:00
[DATE(calldate)] => 2016-03-18
[direction] => outbound
)
What I am hoping to do is create a daterange from my form like below:
//create data range array
$begin = new DateTime( $datefrom );
$end = new DateTime( $dateto );
$end = $end->modify( '+1 day' );
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval ,$end);
And then use a foreach loop to iterate through the selected dates of the daterange and pull the value from the associative array where the dates match and if not insert zero values like below:
[number_of_calls] => 0
[total_call_time] => 00:00:00
[average_call] => 00:00:00
I also need the final array to end up in date order. Can anybody help me with this please?
You can transform your $result array to use DATE(calldate) as keys.
$keys = [];
foreach ($result as $item) {
$keys[] = $item['DATE(calldate)'];
}
$result = array_combine($keys, $result);
And your array will look like that:
[2016-03-18] => Array
(
[number_of_calls] => 151
[total_call_time] => 00:01:30
[average_call] => 00:02:00
[DATE(calldate)] => 2016-03-18
[direction] => outbound
)
And you can check if date is presented by simple command:
$key = $datevalue->format('Y-m-d');
if (isset($result[$key])) {
// date exists, use it
} else {
// date not exists, create empty value
}
This is what I ended up doing
// helper function to recursively search array
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
foreach ($daterange as $datevalue) {
$key = recursive_array_search($datevalue->format('Y-m-d'), $result);
// if date is found write values from data to output array
if ($key !== False) {
$output_array[] = array("number_of_calls" => $result[$key]['number_of_calls'],
"total_call_time" => $result[$key]['total_call_time'],
"average_call" => $result[$key]['average_call'],
"DATE(calldate)" => $datevalue->format('Y-m-d'),
"direction" => "outbound" );
}
// else write zeros
else {
$output_array[] = array("number_of_calls" => "0",
"total_call_time" => "00:00:00",
"average_call" => "00:00:00",
"DATE(calldate)" => $datevalue->format('Y-m-d'),
"direction" => "outbound" );
}
}
$this->chart_data = $output_array;
}

Group column name in database which has same value

I am making a program to add number of stores which has their own opening and closing hours( Which may be different for different days)
My database structure for storing opening and closing hours is as
so while fetching my data from this table I want to group column name having same value..
like for first store output should be
monday, tuesday, wednesday, thrusday, friday, saturday, sunday => 10:00-am to 8:00-pm
And for last store output should be
monday, tuesday, wednesday, friday, saturday => 10:00-am to 8:00-pm
thrusday => 9:30-am to 5:00-pm
sunday => 10:00-am to 4:30-pm
So how I can write query to fetch records like this..
Thank you,
Might this will help you.
$array = which is coming from the database and treating its input as of now.
$standardTime = the array which holds the default opening and closing time for stores.
I am not sure how this will possible with the SQL or direct by the query but, here I have tried to do with the PHP script. Hope this will help you.
$array = array(
'monday' => "10:30-am to 08:00-pm",
'tuesday' => "10:30-am to 08:00-pm",
'wedensday' => "10:30-am to 08:00-pm",
'thursday' => "09:30-am to 05:00-pm",
'friday' => "10:30-am to 08:00-pm",
'saturday' => "10:30-am to 08:00-pm",
'sunday' => "10:00-am to 04:30-pm",
);
$standardTime = array("10:30-am to 08:00-pm","10:30-am to 08:00-pm","10:30-am to 08:00-pm","10:30-am to 08:00-pm","10:30-am to 08:00-pm","10:30-am to 08:00-pm","10:30-am to 08:00-pm");
$diff = array_diff($array,$standardTime);
$daysWithDiffTimmings = '';
if(is_array($diff) && count($diff) > 0) {
$daysThatHaveDiffTime = array_keys($diff);
foreach($daysThatHaveDiffTime as $day) {
$daysWithDiffTimmings.= $day.' = '.$diff[$day]."<br/>";
unset($array[$day]);
}
}
$remainingDaysWithSameTime = array_keys($array);
$daysWithSameTime = implode(",", $remainingDaysWithSameTime);
$daysWithSameTime .= ' = 10:30-am to 08:00-pm<br/>';
echo $daysWithSameTime;
echo $daysWithDiffTimmings;
This will give you output as:
monday,tuesday,wedensday,friday,saturday = 10:30-am to 08:00-pm
thursday = 09:30-am to 05:00-pm
sunday = 10:00-am to 04:30-pm
Try this :
$question = array(
'monday' => '10:00-am to 8:00-pm',
'tuesday' => '10:00-am to 8:00-pm',
'wednesday' => '10:00-am to 8:00-pm',
'thrusday' => '9:30-am to 5:00-pm',
'friday' => '10:00-am to 8:00-pm',
'saturday' => '10:00-am to 8:00-pm',
'sunday' => '10:00-am to 4:30-pm',
);
$result = array();
foreach ($question as $key => $value) {
if(isset($result[$value]))
$result[$value] .= ', '.$key;
else
$result[$value] = $key;
}
echo "<pre>".print_r(array_flip($result),1)."</pre>";
OUTPUT :
Array
(
[monday, tuesday, wednesday, friday, saturday] => 10:00-am to 8:00-pm
[thrusday] => 9:30-am to 5:00-pm
[sunday] => 10:00-am to 4:30-pm
)

Make an Array from another array with using implode()

I have an array.
my array:
while($rowop = mysql_fetch_array($resultop))
{
$info[] = array(
'status'=>$rowop[2],
'day' => $rowop[3],
'from'=>$rowop[4],
'to' => $rowop[5],
'mon'=>$rowop[6],
'tue' => $rowop[7],
'wed'=>$rowop[8],
'thu' => $rowop[9],
'fri'=>$rowop[10],
'sat' => $rowop[11],
'sun'=>$rowop[12]
);
}
value of $rowop[6],$rowop[7],$rowop[8],$rowop[9],$rowop[10],$rowop[11],$rowop[12] can be 'on' or 'off'. I want to show only those rows which contain 'off' value. array will be same as:
'status'=>'ok',
'day' =>'all',
'from'=>'12pm',
'to' => '8am',
'off day'=>'tue,wed,thu,sat,sun'
Any one please give me Idea.if possible give example
Try this, ( assuming your array name is $info ) :
$result = array();
foreach($info as $key=>$value){
$result[$key]['status'] = $value['status'];
$result[$key]['day'] = $value['day'];
$result[$key]['from'] = $value['from'];
$result[$key]['to'] = $value['to'];
$off=array();
foreach ($value as $k => $v) {
if($v=="off") $off[]=$k;
}
if($off) $off_days = implode (", ", $off);
$result[$key]["off day"] = $off_days;
}
print_r($result);
What about this?
$days = ['mon','tue','wed','thu','fri','sat','sun'];
for($offs=[],$i=6,$i<=12,$i++) if($rowtop[$i]=='off') $offs[]= $days[$i-6];
$info[] = array(
'status'=>$rowop[2],
'day' => $rowop[3],
'from'=>$rowop[4],
'to' => $rowop[5],
'off day' => implode(',', $offs)
);
How about following code
I didn't test it. Fix if there are any errors
$days = array('mon','tue', 'wed', 'thu', 'fri', 'sat', 'sun');
$selected = array();
$final = array();
foreach($days as $day)
{
if(isset($info[$day]))
if($info[$day] == 'off')
$selected[] = $info[$day];
}
$all_days = implode(',', $selected);
$final['status'] = $info['status'];
$final['day'] = $info['day'];
$final['from'] = $info['from'];
$final['to'] = $info['to'];
$final['off day'] = $all_days;
This can be achieved in multiple steps:
Find all keys with off status using array_filter() and store it in array $result
Remove all the "week keys", i.e. mon, tue, wed etc. using array_diff_key()
Implode $result array to get a comma-separated string, and use that to create a new array element
Code:
// find all keys with 'off' status
$status = 'off';
$result = array_keys(array_filter($info,
function($element) use ($status) {
return $element == $status;
}
));
// remove all week keys
$keys = array('mon','tue','wed','thu','fri','sat','sun');
$info = array_diff_key($info, array_flip($keys));
// create a new array item with the comma-separated key string
$info['off_days'] = implode(',', $result);
print_r($info);
Output:
Array
(
[status] => ok
[day] => all
[from] => 12pm
[to] => 8am
[off_days] => tue,wed,thu,sat,sun
)
Demo.
An example using array_filter
$days = array('mon','tue', 'wed', 'thu', 'fri', 'sat', 'sun');
while($rowp ....) { //
$offs = implode (
',',
array_keys(
array_filter(
array_intersect_key($oneRow, array_flip($days)),
function($i) {return $i == 'off'}
)
)
);
//...
}
where $oneRow is what you are filling the $info array with.
Hope it helps

PHP: Condense array of similar strings into one merged array

Working with an array of dates (opening times for a business). I want to condense them to their briefest possible form.
So far, I started out with this structure
Array
(
[Mon] => 12noon-2:45pm, 5:30pm-10:30pm
[Tue] => 12noon-2:45pm, 5:30pm-10:30pm
[Wed] => 12noon-2:45pm, 5:30pm-10:30pm
[Thu] => 12noon-2:45pm, 5:30pm-10:30pm
[Fri] => 12noon-2:45pm, 5:30pm-10:30pm
[Sat] => 12noon-11pm
[Sun] => 12noon-9:30pm
)
What I want to achieve is this:
Array
(
[Mon-Fri] => 12noon-2:45pm, 5:30pm-10:30pm
[Sat] => 12noon-11pm
[Sun] => 12noon-9:30pm
)
I've tried writing a recursive function and have managed to output this so far:
Array
(
[Mon-Fri] => 12noon-2:45pm, 5:30pm-10:30pm
[Tue-Fri] => 12noon-2:45pm, 5:30pm-10:30pm
[Wed-Fri] => 12noon-2:45pm, 5:30pm-10:30pm
[Thu-Fri] => 12noon-2:45pm, 5:30pm-10:30pm
[Sat] => 12noon-11pm
[Sun] => 12noon-9:30pm
)
Can anybody see a simple way of comparing the values and combining the keys where they're similar? My recursive function is basically two nested foreach() loops - not very elegant.
Thanks,
Matt
EDIT: Here's my code so far, which produces the 3rd array above (from the first one as input):
$last_time = array('t' => '', 'd' => ''); // blank array for looping
$i = 0;
foreach($final_times as $day=>$time) {
if($last_time['t'] != $time ) { // it's a new time
if($i != 0) { $print_times[] = $day . ' ' . $time; }
// only print if it's not the first, otherwise we get two mondays
} else { // this day has the same time as last time
$end_day = $day;
foreach($final_times as $day2=>$time2) {
if($time == $time2) {
$end_day = $day2;
}
}
$print_times[] = $last_time['d'] . '-' . $end_day . ' ' . $time;
}
$last_time = array('t' => $time, 'd' => $day);
$i++;
}
I don't think there is a particularly elegant solution to this. After much experimenting with the built in array_* functions trying to find a nice simple solution, I gave up and came up with this:
$lastStart = $last = $lastDay = null;
$new = array();
foreach ($arr as $day => $times) {
if ($times != $last) {
if ($last != null) {
$key = $lastStart == $lastDay ? $lastDay : $lastStart . '-' . $lastDay;
$new[$key] = $last;
}
$lastStart = $day;
$last = $times;
}
$lastDay = $day;
}
$key = $lastStart == $lastDay ? $lastDay : $lastStart . '-' . $lastDay;
$new[$key] = $last;
It only uses one foreach loop as opposed to your two, as it keeps a bunch of state. It'll only merge adjacent days together (i.e., you won't get something like Mon-Tue,Thu-Fri if Wednesday is changed, you'll get two separate entries).
I'd approach it by modelling it as a relational database:
day start end
1 12:00 14:45
1 17:30 22:30
...
Then its fairly easy to reduce - there are specific time intervals:
SELECT DISTINCT start, end
FROM timetable;
And these will occur on specific days:
SELECT start, end, GROUP_CONCAT(day) ORDER BY day SEPERATOR ','
FROM timetable
GROUP BY start,end
(this uses the MySQL-only 'group_concat' function - but the method is the same where this is not available)
would give:
12:00 14:45 1,2,3,4,5
17:30 22:30 1,2,3,4,5
12:00 23:00 6
12:00 21:30 7
Then it's fairly simple to work out consecutive date ranges from the list of days.
C.
As an alternative, I managed to cobble together a version using array_* functions. At some point though, 'elegance', 'efficiency' and 'readability' all packed up and left. It does, however, handle the edge cases I mentioned in the other answer, and it left me with a nice warm glow for proving it could be done in a functional manner (yet at the same time a sense of shame...)
$days = array_keys($arr);
$dayIndices = array_flip($days);
var_dump(array_flip(array_map(
function ($mydays) use($days, $dayIndices) {
return array_reduce($mydays,
function($l, $r) use($days, $dayIndices) {
if ($l == '') { return $r; }
if (substr($l, -3) == $days[$dayIndices[$r] - 1]) {
return ((strlen($l) > 3 && substr($l, -4, 1) == '-') ? substr($l, 0, -3) : $l) . '-' . $r;
}
return $l . ',' . $r;
}, '');
}, array_map(
function ($day) use ($arr) {
return array_keys($arr, $arr[$day]);
}, array_flip($arr)
)
)));
I tested it with this input:
'Mon' => '12noon-2:45pm, 5:30pm-10:30pm',
'Tue' => '12noon-2:45pm, 5:30pm-10:30pm',
'Wed' => '12noon-2:45pm, 5:30pm-10:00pm',
'Thu' => '12noon-2:45pm, 5:30pm-10:30pm',
'Fri' => '12noon-2:45pm, 5:30pm-10:00pm',
'Sat' => '12noon-2:45pm, 5:30pm-10:30pm',
'Sun' => '12noon-9:30pm'
And got this:
["Mon-Tue,Thu,Sat"]=> string(29) "12noon-2:45pm, 5:30pm-10:30pm"
["Wed,Fri"]=> string(29) "12noon-2:45pm, 5:30pm-10:00pm"
["Sun"]=> string(13) "12noon-9:30pm"
Basically, the array_map at the end transforms the input into an associative array of times to an array of days that they occur on. The large block of code before that reduces those days into a nicely formatted string using array_reduce, consulting the $days and $dayIndices arrays to check if days are consecutive or not.

Categories