Сортировка массива имен дней недели
у меня есть следующий массив:
(
[0] => Array
(
[schedules] => Array
(
[monday] => 1
[tuesday] => 1
[wednesday] => 1
[thursday] => 1
[friday] => 1
[saturday] => 0
[sunday] => 1
)
)
)
Я хотел бы отсортировать элементы этого массива с первым ключом, который будет завтра. Допустим, сегодня среда. Я бы хотел, чтобы мой массив выглядел так:
(
[0] => Array
(
[schedules] => Array
(
[thursday] => 1
[friday] => 1
[saturday] => 0
[sunday] => 1
[monday] => 1
[tuesday] => 1
[wednesday] => 1
)
)
)
у меня уже есть рабочий день (например, строка "четверг"). Он переходит в функцию, с которой я работаю.
любые предложения для достижения этого типа сортировки? Спасибо!
9 ответов
Если вы преобразуете день в число 0-6, вы можете array_shift
и array_push
столько раз, чтобы переместить предыдущие дни в конец массива.
попробуйте использовать uksort()
. Вы можете сравнить даты в функции обратного вызова, описанной в ссылке.
например:
function compare($a, $b) {
date(strtotime($a)) - date(strtotime($b));
}
uksort($array, "compare");
сначала вам нужен список в правильном порядке, который вы можете захватить через класс DateTime. Затем, когда вы перебираете старый массив, используйте правильный порядок в качестве ключа для сортировки массива, например:
function sort_by_weekday( $input_array) {
$now = new DateTime( "tomorrow", new DateTimeZone('America/New_York'));
$interval = new DateInterval( 'P1D'); // 1 Day interval
$period = new DatePeriod( $now, $interval, 7); // 7 Days
$sorted_array = array();
foreach( $period as $day) {
$weekday = strtolower( $day->format( 'l'));
foreach( $input_array as $key => $value) {
$sorted_array[ $key ][ $weekday ] = $value[ $weekday ];
}
}
return $sorted_array;
}
вы можете видеть, как он работает в демо.
Если вы объедините uksort С простой функцией, это удивительно простое решение.
очевидно, что преобразование строк имени дня в ints необходимо, но если день предшествует текущему буднему Дню, просто добавьте семь к переменной, это гарантирует, что массив будет отсортирован как "после", даже если день недели будет означать иное.
<?php
$a='sunday'; // Example Input
$b='saturday'; // Example Input
function funnyDateCompare($a, $b)
{
$a=date('w',strtotime($a));
$b=date('w',strtotime($b));
if($a<=date('w'))
{
$a+=7;
// First value is less than or equal to today.
// Adding 7 to the answer.
}
return ($a - $b);
}
uksort($array, "funnyDateCompare")
?>
вы можете сделать так, чтобы достичь этого
$week = [
'sunday',
'monday',
'tuesday',
'wednesday',
'thursday',
'friday',
'saturday',
];
$day = date('w'); // weekday as integer(3 for Wednesday)
for ($i=0; $i <= $day ; $i++) {
array_push($week, array_shift($week));
}
$result = $week;
результат (если сегодня среда):
Array
(
[0] => thursday
[1] => friday
[2] => saturday
[3] => sunday
[4] => monday
[5] => tuesday
[6] => wednesday
)
Я написал решение, которое не приводит дни к типу даты/времени, а вместо этого использует закрытие и uksort. По сути, каждый ключ, переданный в uksort, сравнивается с позицией ключа" завтра", и если он " до "завтра, он "продвигается" в будущее (+= 7
), затем используется простой результат сравнения.
редактировать характеристики:
редактирование мотивировано комментарием @nickb (спасибо!)
<?php
function sortedWithNext($days, $tomorrow) {
$index_dictionary = array_combine(array_keys($days), range(0,6));
$index_of_tomorrow = $index_dictionary[$tomorrow];
$compare_function = function($k1, $k2) use ($index_dictionary, $index_of_tomorrow) {
$index_of_k1 = $index_dictionary[$k1];
$index_of_k2 = $index_dictionary[$k2];
if($index_of_k1 < $index_of_tomorrow)
$index_of_k1 += 7;
if($index_of_k2 < $index_of_tomorrow)
$index_of_k2 += 7;
return $index_of_k1 - $index_of_k2;
};
uksort($days, $compare_function);
return $days;
}
$daysPool = array(
'monday'=>1,
'tuesday'=>1,
'wednesday'=>1,
'thursday'=>1,
'friday'=>0,
'saturday'=>1,
'sunday'=>1,
);
$tomorrow = 'thursday';
$sortedDays = sortedWithNext($daysPool, $tomorrow);
var_dump($sortedDays);
производительность Примечания
Я тестировал, используя 100 000 итераций, этот метод тратит примерно 2,2 e-5 секунд на сортировку массива. Любопытные проверят первую версию этого ответа, чтобы найти менее эффективную версию, которая заняла примерно в два раза больше времени, 5.5 e-5 секунд.
это работает для меня, просто простой цикл:
$array = array();
$month = date('m');
$day = date('d');
$year = date('Y');
for($i=1; $i<=7; $i++){
$array[] = date('l',mktime(0,0,0,$month,($day+$i),$year));
}
выходной массив выглядит так: (если сегодня вторник)
array(
(int) 0 => 'Wednesday',
(int) 1 => 'Thursday',
(int) 2 => 'Friday',
(int) 3 => 'Saturday',
(int) 4 => 'Sunday',
(int) 5 => 'Monday',
(int) 6 => 'Tuesday'
)
этот ответ позволяет, какой день недели, чтобы начать, и динамически обрабатывает, как дни помечены.
Это просто улучшенное решение с использованием uksort(), date () и strtotime ().
function sort_days( $term1, $term2 ) {
$weekdays = array( 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat' );
foreach ( $weekdays as $key => $value ) {
$weekdays[ $key ] = date( 'N', strtotime( $value ) );
}
$term1_time = date( 'N', strtotime( strtolower( $term1 ) ) );
$term2_time = date( 'N', strtotime( strtolower( $term2 ) ) );
return array_search( $term1_time, $weekdays ) - array_search( $term2_time, $weekdays );
}
сортировка Ключей с помощью uksort()
$uk_days = array(
'thursday' => 1,
'monday' => 1,
'saturday' => 1,
'wednesday' => 1,
'sunday' => 1,
'friday' => 1,
'tuesday' => 1,
);
uksort($uk_days, "sort_days");
var_dump($uk_days);
сортировка Ключей с помощью usort()
$u_days = array(
'thursday',
'monday',
'saturday',
'wednesday',
'sunday',
'friday',
'tuesday',
);
usort($u_days, "sort_days");
var_dump($u_days);