Сортировка массива имен дней недели

у меня есть следующий массив:

 (
     [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);