javascript - 从数组中的时间间隔计算唯一时间

标签 javascript arrays algorithm logic

我有一种情况需要计算用户播放视频的唯一秒数。我得到一个数组 playbackArray,其中我得到用户开始播放视频的位置 (beginPosition) 和用户停止播放视频的位置 (endPosition).

我有一个这样的数组:

    let playbackArray = [
        {
            beginPosition: 0,
            endPosition: 30, // endPosition - beginPosition = 30
            blockNum: 0
        },
        {
            beginPosition: 45,
            endPosition: 65, // endPosition - beginPosition = 20
            blockNum: 1
        },
        {
            beginPosition: 55,
            endPosition: 85, // endPosition - beginPosition = 30
// but only 20 new seconds (65s - 85s) so total video playback is 30 + 20 + 20 = 70s.
            blockNum: 2
        }
    ]

Basically, if there are overlapping time in the blocks in array, I have to remove those overlapping time interval and calculate only unique time from this array.

我看到的一种方法是以某种方式在这个数组上运行一个循环并遍历每个 block 并将当前 block 的 beginPosition 与前一个 block 的 endPosition 和

  1. 如果没有重叠,将这个差异添加到另一个数组中。
  2. 如果有重叠,则将当前 block 的 beginPosition 与之前所有 block 的 beginPosition 进行比较,并尝试将差值扣除到此数组中。

最佳答案

如果间隔首先按其开始时间段排序,那么我们可以根据三种情况将我们的测试间隔 (-[--]-) 添加到不断增长的间隔列表 (-<-->-):

// 1: Ignore current interval
      ----[--<--->--]----
      ----[---------]---- 

// 2: Merge top and current
      ----[--<---]-->----
      ----[---------]---- 

// 3: Add current to stack
      ----[---]---<-->---
      ----[---]---[--]---

这是一个执行此操作的实现。示例数据涵盖了所有这些情况,并且没有开始排序。您可以删除 sort行(以及它上面的 slice 调用)如果您的数据将始终按间隔开始排序:

// Example: ['a', 'b', 'c', 'd'] //=> 'd'
const last = stack => stack[stack.length - 1] 
// Example: ['a', 'b', 'c', 'd'] //=> ['a', 'b', 'c']
const init = stack => stack.slice(0, stack.length - 1) 
const start = interval => interval.beginPosition
const end = interval => interval.endPosition

const consolidateOverlaps = (intervals) => 
    intervals.slice(0) // don't mutate original array
    .sort((a, b) => start(a) < start(b) ? -1 : start(a) > start(b) ? 1 : 0)
    .reduce((stack, curr) => start(curr) < end(last(stack))
      ? end(curr) < end(last(stack)) 
        ? stack // Case 1
        : init(stack).concat(Object.assign(last(stack), {endPosition: end(curr)})) // Case 2
      : stack.concat(curr) // Case 3
    , [{endPosition: -Infinity}]) // base case to start reduction
    .slice(1) // remove that (now unnecessary) base case

const playbackArray = [
  {beginPosition: 0, endPosition: 30, blockNum: 0},
  {beginPosition: 45, endPosition: 65, blockNum: 1},
  {beginPosition: 55, endPosition: 85, blockNum: 2},
  {beginPosition: 90, endPosition: 110, blockNum: 3},
  {beginPosition: 95, endPosition: 100, blockNum: 4},
  {beginPosition: 20, endPosition: 40, blockNum: 5},
  {beginPosition: 130, endPosition: 200, blockNum: 6},
  {beginPosition: 140, endPosition: 250, blockNum: 7},
  {beginPosition: 150, endPosition: 225, blockNum: 8},
]

console.log(consolidateOverlaps(playbackArray))

请注意生成的 blockNums现在相当随意。将此结果转换为总秒数应该很容易:

consolidateOverlaps(playbackArray)
  .map(interval => interval.endPosition - interval.beginPosition)
  .reduce((a, b) => a + b, 0)

(如果您不需要间隔列表,这两行可以折叠到原始函数中。)

关于javascript - 从数组中的时间间隔计算唯一时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49802502/

相关文章:

javascript - +new Date() 和 1*new Date() 的区别

javascript - reloadOnSearch :false 时返回按钮

c++ - 这段代码是什么意思?打开简历

javascript - 算法得到的数组总和,小于一个限制

javascript - 使用外部 javascript 文件触发 HTML 类

javascript - Oracle Apex 树选定的节点不起作用

c - 删除前面的空格的程序

PHP:找到多个字符串之间最大的重叠

java - 找不到类?

c# - 文本框自动完成 - Winform + LINQ