kinamartin
kinamartin

Reputation: 45

Check many conditions in a loop of an array of objects efficiently

I have an array of objects and one property is their statuses, I need to calculate the status following this: if all the statuses are failed return "failed", if all are canceled return "canceled", and so on, but if the array has one failed, or one canceled return "partially completed", I did, but I am looping a lot and I feel that exist a better and efficient way to do the same, this is my code:

function getComputedStatus(list) {

      if (list.every(status => status.statusName == 'Failed'))
          return 'Failed';

      if (list.every(status => status.statusName == 'Canceled'))
          return 'Canceled';

      if (list.every(status => status.statusName == 'DidNotRun'))
          return 'DidNotRun';

      if (list.some(status => status.statusName == 'InProgress' ||
          status.statusName == 'Pending'))
          return 'InProgress';

      if (list.some(status => status.statusName === 'Failed'   ||
                              status.statusName === 'Canceled' ||
                              status.statusName === 'DidNotRun'))
         return 'PartiallyCompleted';

      return 'Completed';
}

Upvotes: 2

Views: 67

Answers (1)

jfriend00
jfriend00

Reputation: 707876

So, it appears that your logic is actually this:

  1. You have an array of status objects.
  2. If any status is 'InProgress' or 'Pending', then return 'InProgress'
  3. If all statuses are the same and are 'Failed', 'Canceled' or 'DidNotRun', then return that value.
  4. If any status are 'Failed', 'Canceled' or 'DidNotRun', then return 'PartiallyCompleted'
  5. Otherwise, return 'Completed'

So, there would be a huge efficiency of execution gain if you can figure out how to do all these checks with one pass through the array instead of your 5 partial passes through the array.

Here's one way to do that:

const doneStatuses = new Set(["Failed", "Canceled", "DidNotRun", "Completed", "InProgress"]);

function getComputedStatus(list) {
    const allStatuses = new Set();

    // collect all status values in a Set object
    for (let status of list) {
        allStatuses.add(status.statusName);
    }

    // if all the statusName values were the same and they were  
    // "Failed", "Canceled", "DidNotRun", "InProgess" or "Completed"
    // then return that specific status
    if (allStatuses.size === 1) {
        let theStatus = Array.from(allStatuses)[0];
        if (doneStatuses.has(theStatus)) {
            return theStatus;
        }
    }
    // if any status was "InProgress" or "Pending", return "InProgress"
    if (allStatuses.has("InProgress") || allStatuses.has("Pending")) {
        return "InProgress";
    }

    // If any status was "Failed", "Canceled" or "DidNotRun" (but not all)
    // then return "PartiallyCompleted"
    if (allStatuses.has("Failed") || allStatuses.has("Canceled") || allStatuses.has("DidNotRun")) {
        return "PartiallyCompleted";
    }

    // otherwise, return "Completed"
    return "Completed";
}

Upvotes: 3

Related Questions