dongliming2416 2013-04-25 12:57
浏览 40
已采纳

无法根据2个变量找出usort逻辑

I have an array of objects (goals) that I want to sort based on 2 of their properties, the Status and the DueDate.

Here are the rules:

Statuses:

  1. Design
  2. Approved
  3. In Progress
  4. Completed
  5. Archived

If a goal has a status of 4 (completed) or 5 (archived) then the DueDate doesn't matter.

If a goal is neither 4 nor 5 and its DueDate is less than now then it is "Overdue" and should be at the top

If a goal is not "Overdue" then the order of statuses determines it's position (lowest to highest)

If $a and $b are both "Overdue" then the one with the earliest DueDate is more important

The order should be:

  1. Overdue
  2. Design
  3. Approved
  4. In Progress
  5. Completed
  6. Archived

Here is the last thing I tried:

function cmp($a, $b)
{
    $now = new DateTime("now");
    $aDueDate = new DateTime($a->GetDueDate());
    $bDueDate = new DateTime($b->GetDueDate());

if($a->GetStatus() != 4 && $a->GetStatus() != 5 && $b->GetStatus() != 4 && $b->GetStatus() != 5){
    if($aDueDate < $now || $bDueDate < $now){
        if($aDueDate == $bDueDate){
        return 0;
    }

    return ($aDueDate < $bDueDate) ? -1 : 1;
    }
}
elseif(($a->GetStatus() == 4 || $a->GetStatus() == 5) && ($b->GetStatus() != 4 && $b->GetStatus() != 5)) {
    return -1;
}
elseif(($a->GetStatus() != 4 && $a->GetStatus() != 5) && ($b->GetStatus() == 4 || $b->GetStatus() == 5)){
    return 1;
}

if ($a->GetStatus() == $b->GetStatus()) {
        return 0;
    }
    return ($a->GetStatus() < $b->GetStatus()) ? -1 : 1;
}

Which orders the array like so:

  1. Completed
  2. Archived
  3. Overdue
  4. Design
  5. Approved
  6. In Progress
  • 写回答

1条回答 默认 最新

  • dongzha0813 2013-04-25 13:25
    关注

    The following should meet your requirements:

    function cmp($a, $b) {
        $now = new DateTime("now");
        $aDueDate = new DateTime($a->GetDueDate());
        $bDueDate = new DateTime($b->GetDueDate());
        $aStatus = $a->GetStatus();
        $bStatus = $b->GetStatus();
        $incompleteStatuses = array(1, 2, 3); 
    
        // use date if same status (might not be needed)    
        if ($aStatus == $bStatus) {
            return ($aDueDate < $bDueDate ? -1 : 1); 
        }   
    
        // if A is overdue:
        if (in_array($aStatus, $incompleteStatuses) && $aDueDate < $now) {
            // if B is overdue too, only consider dates
            if (in_array($bStatus, $incompleteStatuses) && $bDueDate < $now) {
                return ($aDueDate < $bDueDate ? -1 : 1); 
            }   
    
            return -1; // A definitely first
        }   
        // if B is overdue:
        elseif (in_array($bStatus, $incompleteStatuses) && $bDueDate < $now) {
            return 1; // B definitely first (we know A is not overdue from above)
        }   
    
        // both A and B are not overdue; order by status
        return $aStatus - $bStatus;
    }
    

    Here's a test codepad.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 求个正点原子stm32f407开发版的贪吃蛇游戏
  • ¥15 正弦信号发生器串并联电路电阻无法保持同步怎么办
  • ¥15 划分vlan后,链路不通了?
  • ¥20 求各位懂行的人,注册表能不能看到usb使用得具体信息,干了什么,传输了什么数据
  • ¥15 个人网站被恶意大量访问,怎么办
  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 Centos / PETGEM
  • ¥15 划分vlan后不通了
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)