2012-07-16 46 views
7

我有以下阵列:排序工作日名称的数组

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

     ) 
) 

我已经有星期几可用(例如字符串'星期四')。它被传递到我正在使用的函数中。

有关实现此类排序的任何建议?谢谢!

回答

4

如果将日期转换为数字0-6,您可以多次将array_shiftarray_push转换为数组的末尾。

+0

你们对我的情况下,最简单的解决方案。如果你能告诉我如何得到一天,作为'当前明天'的一个数字(0-6) – kwikness 2012-07-16 17:22:25

+0

对不起,迟到的答复...'日期('N')%7'会为你做那个。 N返回一个数字1-7,所以'date('N')%7'将成为我们0-6号码的第二天。 – 2012-07-20 02:59:13

3

尝试使用uksort()。您可以比较链接中描述的回调函数中的日期。

例如:

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

uksort($array, "compare"); 

这里的proof of it working

+0

它是如何考虑OP的“限制排列这个数组的元素,第一个键是明天的[星期]日”? – nickb 2012-07-16 02:48:10

+1

我在下面使用的代码也是uksort,但只需稍作调整以满足'从今天开始...'的要求。 – Fluffeh 2012-07-16 03:52:25

+0

@Martin,你不需要在'compare'函数中使用'return'吗?另外,为什么你不能只使用'strtotime($ a) - strtotime($ b)'? – parrker9 2016-03-07 07:31:36

1

首先,你需要以正确的顺序,您可以通过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; 
} 

你可以看到它在the demo工作。

3

您可以通过date函数获取星期几。星期日是0,星期一是1,等等。

$weekday = date("w"); 

然后,我建议使用uksort函数到所述阵列相对于它的键,这需要一个回调函数作为排序准则排序。

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

我写了一个解决方案,它不会将日期转换为日期/时间类型,而是使用闭包和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); 

性能指出

我使用10万次迭代测试,这种方法花费大约2.2E-5秒排序数组。好奇的人会检查这个答案的第一个版本,以找到一个性能较低的版本,花费两倍长,5.5e-5秒。

+1

由于'array_search'是O(n),并且您在回调中重复调用'array_search'和'array_keys'以进行排序,所以这可能不是非常有效。 – nickb 2012-07-16 02:49:35

+0

这是一个相当简单的重构(至少其中一个......) – 2012-07-16 03:22:14

+0

并且在另一个小重构中,所有重函数已从闭包中移除;感谢您的输入,@nickb :-) – 2012-07-16 03:39:47

1

如果您将uksort与简单的功能相结合,这是一个非常简单的解决方案。

很明显,将日期名称字符串转换为整数是必要的,但是如果日期早于当前工作日,只需将7添加到变量中,即可保证数组按照'after'排序,即使否则这一周将意味着。

<?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

这是为我工作,只是一个简单的循环:

$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' 
) 
0

此解答允许其日本周开始,并动态处理日子如何标记。

这只是一个改进的解决方案,使用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);