我有一种情况需要计算用户播放视频的唯一秒数。我得到一个数组 playbackArray ,其中我得到了用户开始播放视频的位置( beginPosition )以及用户停止播放视频的位置( endPosition < / em>的)。
我有一个这样的数组:
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
}
]
基本上,如果数组中的块有重叠时间,我 必须删除那些重叠的时间间隔并仅计算 这个阵列的独特时间。
我看到的一种方法是以某种方式在这个数组上运行一个循环并遍历每个块,并将当前块的beginPosition与前一个块的endPosition进行比较,并且
答案 0 :(得分:2)
如果区间首先按其开始时段排序,那么我们可以根据三种情况添加一个不断增加的区间列表(-[--]-
)我们的测试间隔(-<-->-
):
// 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)
(如果您不需要间隔列表,这两行可以折叠成原始函数。)
答案 1 :(得分:1)
非常棒的挑战。
我将在时间跨度之间进行迭代,并确定将其视为重复的时间。为此我想到了下一个可能的案例。
我希望这就是你要找的东西:)
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
}
]
let repeat=0;
let time = 0;
for(var i =0; i<playbackArray.length; i++){
time += playbackArray[i].endPosition - playbackArray[i].beginPosition;
for(var j=i+1; j<playbackArray.length; j++){
if(playbackArray[i].beginPosition > playbackArray[i+1].beginPosition ) {
//play i starts inside play j
if(playbackArray[i].endPosition < playbackArray[i+1].endPosition ) {
//All play i is inside play j
repeat += playbackArray[i].endPosition - playbackArray[i].beginPosition;
} else {
//Play i ends after play j
repeat += playbackArray[j].endPosition - playbackArray[i].beginPosition;
}
}
if(playbackArray[i].endPosition > playbackArray[j].beginPosition ) {
//play i ends after play j started
if(playbackArray[i].endPosition > playbackArray[j].endPosition ) {
//play i ends after play j ended
repeat += playbackArray[j].endPosition - playbackArray[i].beginPosition;
} else {
//play i ends inside play j
repeat += playbackArray[i].endPosition - playbackArray[j].beginPosition;
}
}
}
}
console.log("Total time:"+time,"Repeated time:"+repeat);
var res = time-repeat;
console.log("Real time:"+res);