按两个日期和规则对数组进行排序
Sort Array by two dates and rules
我正在建立一个活动列表日历。事件具有开始日期和结束日期,日期以 YYYYMMDD 格式存储。活动列表按天查看,活动可以是一天,也可以是多天。
事件当前存储在数组中,start_date
和 end_date
我怎样才能:
- 将在当前日期开始的任何事件移到顶部
数组。
- 然后按开始日期对事件进行排序
- 然后按结束日期对事件进行排序
已经看到这个question,但是我在想如何建立上面的逻辑。
将在当前日期开始的任何事件移到数组的顶部,但让其他事件按原样排列!
$today = date('Ymd',strtotime('today'));
usort($events,function($a,$b) use($today){
if($a['start_date'] === $today && $b['start_date'] != $today){return -1;}
else if($b['start_date'] === $today && $a['start_date'] != $today){return 1;}
else {return strnatcmp($a['start_date'],$b['start_date']);}
});
或按开始日期排序事件
usort($events,function($a,$b){
return strnatcmp($a['start_date'],$b['start_date']);
});
或按结束日期对事件排序
usort($events,function($a,$b){
return strnatcmp($a['end_date'],$b['end_date']);
});
编辑一些测试数据:
//example works best if today is 20170810
$events = array(
array(
'name' => 'a',
'start_date' => '20170810',
'end_date' => '20170811',
),
array(
'name' => 'b',
'start_date' => '20170810',
'end_date' => '20170810',
),
array(
'name' => 'c',
'start_date' => '20170607',
'end_date' => '20170608',
),
array(
'name' => 'd',
'start_date' => '20170607',
'end_date' => '20170607',
),
array(
'name' => 'e',
'start_date' => '20170810',
'end_date' => '20170812',
),
array(
'name' => 'f',
'start_date' => '20170807',
'end_date' => '20170817',
),
);
print_r($events);
编辑:全部加在一起: 事件按 'Are they starting today?'、'start_date'、'end_date'
排序
$today = date('Ymd',strtotime('today'));
usort($events,function($a,$b) use($today){
//one of them starts today
if($a['start_date'] === $today && $b['start_date'] != $today){return -1;}
else if($b['start_date'] === $today && $a['start_date'] != $today){return 1;}
//both or neither start today, compare start_date
else {
if($a['start_date'] != $b['start_date']){
//start_dates differ, order by them
return strnatcmp($a['start_date'],$b['start_date']);
} else {
//start dates are the same, order by end_date
return strnatcmp($a['end_date'],$b['end_date']);
}
}
});
print_r($events);
编辑:进行中 事件按 'Are they currently ongoing?'、'start_date'、'end_date'
排序
$today = date('Ymd',strtotime('today'));
//function compares two elements to decide their position relative to each other
usort($events,function($a,$b) use($today){
//check if event is currently ongoing
//starts or ends today or today is between start and end
$ongoing = function($event) use($today){
//this is the simplest form I could think of for the check
return (strnatcmp($event['start_date'],$today) < 1 && strnatcmp($today,$event['end_date']) < 1);
};
$startstoday = function($event) use($today){
return $event['start_date'] === $today;
};
//only one of them is ongoing
if($ongoing($a) && !$ongoing($b)){return -1;}
else if($ongoing($b) && !$ongoing($a)){return 1;}
//both or neither are ongoing, compare start_date
else {
if($a['start_date'] != $b['start_date']){
//start_dates differ, order by them
return strnatcmp($a['start_date'],$b['start_date']);
} else {
//start dates are the same, order by end_date
return strnatcmp($a['end_date'],$b['end_date']);
}
}
});
print_r($events);
编辑:今天开始并持续进行 活动按 'Are they starting today?'、'Are they currently ongoing?'、'start_date'、'end_date'[= 排序18=]
$today = date('Ymd',strtotime('today'));
//function compares two elements to decide their position relative to each other
usort($events,function($a,$b) use($today){
//check if event is currently ongoing
//starts or ends today or today is between start and end
$ongoing = function($event) use($today){
//this is the simplest form I could think of for the check
return (strnatcmp($event['start_date'],$today) < 1 && strnatcmp($today,$event['end_date']) < 1);
};
//only one of them is ongoing
if($ongoing($a) && !$ongoing($b)){return -1;}
else if($ongoing($b) && !$ongoing($a)){return 1;}
//both are ongoing
else if($ongoing($a) && $ongoing($b)){
//one starts today
if($a['start_date'] === $today && $b['start_date'] != $today){return -1;}
else if($b['start_date'] === $today && $a['start_date'] != $today){return 1;}
//both start today
else if($a['start_date'] === $today && $b['start_date'] === $today){
return strnatcmp($a['end_date'],$b['end_date']);
}
//none starts today
else {
if($a['start_date'] != $b['start_date']){
//start_dates differ, order by them
return strnatcmp($a['start_date'],$b['start_date']);
} else {
//start dates are the same, order by end_date
return strnatcmp($a['end_date'],$b['end_date']);
}
}
} else {
//neither are ongoing, compare start_date
if($a['start_date'] != $b['start_date']){
//start_dates differ, order by them
return strnatcmp($a['start_date'],$b['start_date']);
} else {
//start dates are the same, order by end_date
return strnatcmp($a['end_date'],$b['end_date']);
}
}
});
print_r($events);
最后一个可以简化为:
$today = date('Ymd',strtotime('today'));
usort($events,function($a,$b) use($today){
$ongoing = function($event) use($today){
return (strnatcmp($event['start_date'],$today) < 1 && strnatcmp($today,$event['end_date']) < 1);
};
if($ongoing($a)){
if(!$ongoing($b)){return -1;}
else {
if($a['start_date'] === $today && $b['start_date'] != $today){return -1;}
else if($b['start_date'] === $today && $a['start_date'] != $today){return 1;}
}
} else if($ongoing($b)){return 1;}
if($a['start_date'] != $b['start_date']){
return strnatcmp($a['start_date'],$b['start_date']);
} else {
return strnatcmp($a['end_date'],$b['end_date']);
}
});
print_r($events);
我正在建立一个活动列表日历。事件具有开始日期和结束日期,日期以 YYYYMMDD 格式存储。活动列表按天查看,活动可以是一天,也可以是多天。
事件当前存储在数组中,start_date
和 end_date
我怎样才能:
- 将在当前日期开始的任何事件移到顶部 数组。
- 然后按开始日期对事件进行排序
- 然后按结束日期对事件进行排序
已经看到这个question,但是我在想如何建立上面的逻辑。
将在当前日期开始的任何事件移到数组的顶部,但让其他事件按原样排列!
$today = date('Ymd',strtotime('today'));
usort($events,function($a,$b) use($today){
if($a['start_date'] === $today && $b['start_date'] != $today){return -1;}
else if($b['start_date'] === $today && $a['start_date'] != $today){return 1;}
else {return strnatcmp($a['start_date'],$b['start_date']);}
});
或按开始日期排序事件
usort($events,function($a,$b){
return strnatcmp($a['start_date'],$b['start_date']);
});
或按结束日期对事件排序
usort($events,function($a,$b){
return strnatcmp($a['end_date'],$b['end_date']);
});
编辑一些测试数据:
//example works best if today is 20170810
$events = array(
array(
'name' => 'a',
'start_date' => '20170810',
'end_date' => '20170811',
),
array(
'name' => 'b',
'start_date' => '20170810',
'end_date' => '20170810',
),
array(
'name' => 'c',
'start_date' => '20170607',
'end_date' => '20170608',
),
array(
'name' => 'd',
'start_date' => '20170607',
'end_date' => '20170607',
),
array(
'name' => 'e',
'start_date' => '20170810',
'end_date' => '20170812',
),
array(
'name' => 'f',
'start_date' => '20170807',
'end_date' => '20170817',
),
);
print_r($events);
编辑:全部加在一起: 事件按 'Are they starting today?'、'start_date'、'end_date'
排序$today = date('Ymd',strtotime('today'));
usort($events,function($a,$b) use($today){
//one of them starts today
if($a['start_date'] === $today && $b['start_date'] != $today){return -1;}
else if($b['start_date'] === $today && $a['start_date'] != $today){return 1;}
//both or neither start today, compare start_date
else {
if($a['start_date'] != $b['start_date']){
//start_dates differ, order by them
return strnatcmp($a['start_date'],$b['start_date']);
} else {
//start dates are the same, order by end_date
return strnatcmp($a['end_date'],$b['end_date']);
}
}
});
print_r($events);
编辑:进行中 事件按 'Are they currently ongoing?'、'start_date'、'end_date'
排序$today = date('Ymd',strtotime('today'));
//function compares two elements to decide their position relative to each other
usort($events,function($a,$b) use($today){
//check if event is currently ongoing
//starts or ends today or today is between start and end
$ongoing = function($event) use($today){
//this is the simplest form I could think of for the check
return (strnatcmp($event['start_date'],$today) < 1 && strnatcmp($today,$event['end_date']) < 1);
};
$startstoday = function($event) use($today){
return $event['start_date'] === $today;
};
//only one of them is ongoing
if($ongoing($a) && !$ongoing($b)){return -1;}
else if($ongoing($b) && !$ongoing($a)){return 1;}
//both or neither are ongoing, compare start_date
else {
if($a['start_date'] != $b['start_date']){
//start_dates differ, order by them
return strnatcmp($a['start_date'],$b['start_date']);
} else {
//start dates are the same, order by end_date
return strnatcmp($a['end_date'],$b['end_date']);
}
}
});
print_r($events);
编辑:今天开始并持续进行 活动按 'Are they starting today?'、'Are they currently ongoing?'、'start_date'、'end_date'[= 排序18=]
$today = date('Ymd',strtotime('today'));
//function compares two elements to decide their position relative to each other
usort($events,function($a,$b) use($today){
//check if event is currently ongoing
//starts or ends today or today is between start and end
$ongoing = function($event) use($today){
//this is the simplest form I could think of for the check
return (strnatcmp($event['start_date'],$today) < 1 && strnatcmp($today,$event['end_date']) < 1);
};
//only one of them is ongoing
if($ongoing($a) && !$ongoing($b)){return -1;}
else if($ongoing($b) && !$ongoing($a)){return 1;}
//both are ongoing
else if($ongoing($a) && $ongoing($b)){
//one starts today
if($a['start_date'] === $today && $b['start_date'] != $today){return -1;}
else if($b['start_date'] === $today && $a['start_date'] != $today){return 1;}
//both start today
else if($a['start_date'] === $today && $b['start_date'] === $today){
return strnatcmp($a['end_date'],$b['end_date']);
}
//none starts today
else {
if($a['start_date'] != $b['start_date']){
//start_dates differ, order by them
return strnatcmp($a['start_date'],$b['start_date']);
} else {
//start dates are the same, order by end_date
return strnatcmp($a['end_date'],$b['end_date']);
}
}
} else {
//neither are ongoing, compare start_date
if($a['start_date'] != $b['start_date']){
//start_dates differ, order by them
return strnatcmp($a['start_date'],$b['start_date']);
} else {
//start dates are the same, order by end_date
return strnatcmp($a['end_date'],$b['end_date']);
}
}
});
print_r($events);
最后一个可以简化为:
$today = date('Ymd',strtotime('today'));
usort($events,function($a,$b) use($today){
$ongoing = function($event) use($today){
return (strnatcmp($event['start_date'],$today) < 1 && strnatcmp($today,$event['end_date']) < 1);
};
if($ongoing($a)){
if(!$ongoing($b)){return -1;}
else {
if($a['start_date'] === $today && $b['start_date'] != $today){return -1;}
else if($b['start_date'] === $today && $a['start_date'] != $today){return 1;}
}
} else if($ongoing($b)){return 1;}
if($a['start_date'] != $b['start_date']){
return strnatcmp($a['start_date'],$b['start_date']);
} else {
return strnatcmp($a['end_date'],$b['end_date']);
}
});
print_r($events);