1

I have an array of objects like so, where action is always either "start" or "stop", and the time is a UNIX millisecond timestamp (simplified here).

[
  {
    action: "start",
    time: 100,
  },
  {
    action: "stop",
    time: 150
  },
  {
    action: "start",
    time: 250
  },
  {
    action: "stop",
    time: 350
  }
]

I need to find out the total amount of elapsed time between each "start" and "stop". In this case, the correct answer would be 150, because

(150 - 100) + (350 - 250) = 150

It is possible for the array to end in a "start" entry, in which case the difference would be between that time and Date.now().

It has however been ensured that the array is sorted by time, and "start" and "stop" entries will necessarily alternate properly.

How can I go about this?

Emphram Stavanger
  • 4,158
  • 9
  • 35
  • 63

4 Answers4

5

You could check the item, if start, then subtract the value, otherwise add the value.

For the initial value of Array#reduce, you could check the last element and use the actual epoc time as start value, otherwise 0.

var data = [{ action: "start", time: 100 }, { action: "stop", time: 150 }, { action: "start", time: 250 }, { action: "stop", time: 350 }, { action: "start", time: 400 }],
    end = 450, // should be Date.now(),
    sum = data.reduce(function (r, a) {
        return r + (a.action === 'start' ? -a.time : a.time);
    }, data[data.length - 1].action === 'start' ? end : 0);

console.log(sum);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

Actually it is not complicated as you think. You can basically apply addition on each group (start and stop in your case), after that substract totalStart from totalStop. For the "additional start" case which you mentioned, you can add an extra condition.

var data = [{action: "start",time: 100,}, {action: "stop",time: 150}, {action: "start",time: 250}, {action: "stop",time: 350}, {action: "start",time: 375}, ];
totalStart = 0;
totalStop = 0;
isComplete = true;

data.forEach(function(el) {
    if (el.action == "start") {
        isComplete = false;
        totalStart += el.time;
    } else if (el.action == "stop") {
        isComplete = true;
        totalStop += el.time;
    }
});

if (!isComplete) {
    totalStop += 400; //  Date().now() in your case
}

alert(totalStop - totalStart);

Also there are lots of alternatives to do that.

  1. You can use built-in "reduce" function.
  2. You can iterate over array as a two items at a time. for(i=0; i < dataSize; i = i+2)
Tuğca Eker
  • 1,493
  • 13
  • 20
0

Check first if the array ends with a start entry and calculate the difference between time and new Date().now()
In that case remove the last entry. After that just use the reduce code from the previous answer.

Ivaylo Stoev
  • 457
  • 3
  • 7
0

I'm not well versed with JavaScript

difference would be between that time and new Date().now().

<html>
    <head>
        <script language="JavaScript">
     function getTimeDifference() {
                var timeArray = [
                      {
            action: "start",
     time: 100,
        },
        {
     action: "stop",
     time: 150
        },
        {
     action: "start",
     time: 250
        },
        {
     action: "stop",
     time: 350
        },
        {
     action: "start",
     time: 100,
        }
    ];
         var size = timeArray.length;
         var timeDiff = 0;
  if(timeArray[size-1].action == 'start') {
      // timeDiff = this.time - new Date().now();
  }
  else {
      var startTime = 0;
      var endTime = 0;    
      for(var i=0; i<size; i++) {        
   if(timeArray[i].action == 'start')
       startTime = startTime + timeArray[i].time;
   else if(timeArray[i].action == 'stop')
       endTime = endTime + timeArray[i].time;     
      }
      timeDiff = endTime - startTime;
  }
  alert(timeDiff);
     }
 </script>
    </head>
    <body>
 <input type="button" onclick="getTimeDifference()"/>
    </body>
</html>

As you can see inside the condition of array ending with action as start I haven't made the calculation, because I not sure about the procedure.

Arun Sudhakaran
  • 2,167
  • 4
  • 27
  • 52