2012-07-16 7 views
7

tengo la siguiente matriz:Ordenación de un conjunto de nombres entre semana

(
    [0] => Array 
     (
      [schedules] => Array 
       (
        [monday] => 1 
        [tuesday] => 1 
        [wednesday] => 1 
        [thursday] => 1 
        [friday] => 1 
        [saturday] => 0 
        [sunday] => 1 
       ) 

     ) 

) 

me gustaría ordenar los elementos de esta matriz con la primera clave es el día de mañana. Digamos que hoy fue miércoles. Me gustaría que mi matriz a tener este aspecto:

(
    [0] => Array 
     (
      [schedules] => Array 
       (
        [thursday] => 1 
        [friday] => 1 
        [saturday] => 0 
        [sunday] => 1 
        [monday] => 1 
        [tuesday] => 1 
        [wednesday] => 1 
       ) 

     ) 
) 

Ya tengo el día de la semana disponibles (por ejemplo, una cadena 'Jueves'). Se pasa a la función con la que estoy trabajando.

¿Alguna sugerencia para lograr este tipo de clasificación? ¡Gracias!

Respuesta

4

Si convierte el día a un número 0-6 puede array_shift y array_push tantas veces para mover los días anteriores al final de la matriz.

+0

que tienen la solución más simple para mi caso. la mejor respuesta es para usted si puede decirme cómo obtener el día, como un número (0-6) del 'mañana actual' – kwikness

+0

Disculpe la última respuesta ... 'fecha ('N')% 7' haz eso por ti. N devuelve un número 1-7, por lo que 'date ('N')% 7' será el día siguiente en nuestra numeración 0-6. –

3

Intente utilizar uksort(). Puede comparar fechas en la función de devolución de llamada descrita en el enlace.

Por ejemplo:

function compare($a, $b) { 
    date(strtotime($a)) - date(strtotime($b)); 
} 

uksort($array, "compare"); 

Aquí es proof of it working

+0

¿Cómo se tiene en cuenta la restricción de OP de "ordenar los elementos de esta matriz con la primera clave el [semana] día [de] mañana"? – nickb

+1

El código que utilicé a continuación también es un uksort, pero con un pequeño ajuste para la solicitud 'ordenar a partir de hoy en adelante ...'. – Fluffeh

+0

@Martin, ¿no necesita usar 'return' en la función' compare'? Además, ¿por qué no puedes usar 'strtotime ($ a) - strtotime ($ b)'? – parrker9

1

Lo primero que necesita una lista en el orden correcto, que se puede agarrar a través de la clase DateTime. Entonces, como se recorre la vieja matriz, utilice el orden correcto como la clave para ordenar la matriz, así:

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; 
} 

Puede ver su funcionamiento en the demo.

3

Puede obtener el día de la semana a través de la función date. El domingo es 0, el lunes es 1, y así sucesivamente.

$weekday = date("w"); 

A continuación, se sugiere emplear la función uksort para ordenar la matriz en relación con sus llaves, que tiene una función de devolución de llamada como una guía de clasificación.

uksort($schedules, function ($a, $b) use ($weekday) { 
    // convert each day to a number 0-6 and compare to $weekday 
}); 
0

Escribí una solución que no convierte los días a un tipo de fecha/hora, sino que utiliza un cierre y uksort. Esencialmente, cada clave que pasa a uksort se compara con la posición de la tecla "mañana", y si es "antes" mañana, se "promociona" en el futuro (+= 7), luego se usa un resultado de comparación simple.

editado para el rendimiento: (gracias)

ediciones motivados por el comentario de @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); 

Notas de rendimiento

probé usando 100.000 iteraciones, este método gasta aproximadamente 2.2e-5 segundos para ordenar la matriz. El curioso comprobará la primera versión de esta respuesta para encontrar una versión menos eficiente que requirió el doble de tiempo, 5.5e-5 segundos.

+1

Dado que 'array_search' es O (n) y llama repetidamente tanto a' array_search' como a 'array_keys' en una devolución de llamada para ordenar, es probable que esto no sea muy eficiente. – nickb

+0

Es un refactor bastante sencillo (al menos uno de ellos ...) –

+0

Y con otro refactor pequeño, todas las funciones pesadas se han eliminado del cierre; gracias por la entrada, @nickb :-) –

1

Si combina un uksort con una función simple, esta es una solución sorprendentemente fácil.

Obviamente, es necesario convertir las cadenas de nombre del día en enteros, pero si el día es anterior al día de la semana actual, simplemente agregue siete a la variable, que garantizará que la matriz esté ordenada como 'después' aunque el día de la semana implicaría lo contrario.

<?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") 
?> 
0

Esto es trabajo para mí, sólo un simple bucle:

$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)); 
} 

matriz de salida será similar a: (Si hoy en día es un martes)

array(
    (int) 0 => 'Wednesday', 
    (int) 1 => 'Thursday', 
    (int) 2 => 'Friday', 
    (int) 3 => 'Saturday', 
    (int) 4 => 'Sunday', 
    (int) 5 => 'Monday', 
    (int) 6 => 'Tuesday' 
) 
0

Esta respuesta permite a los cuales Día de la semana para comenzar y maneja dinámicamente cómo se etiquetan los días.

Esto es simplemente una solución mejorada que usa uksort(), date() y 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); 
} 

teclas selectoras con 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); 

teclas selectoras con usort()

$u_days = array(
    'thursday', 
    'monday', 
    'saturday', 
    'wednesday', 
    'sunday', 
    'friday', 
    'tuesday', 
); 
usort($u_days, "sort_days"); 
var_dump($u_days); 
Cuestiones relacionadas