Javascript 主干集合:迭代&;有效搜索
我所拥有的:我正在编写我非常琐碎的媒体播放器。所以在它的某个地方我收集了一些字幕(比如说每部电影大约有2000个)。所以每个字幕看起来像:Javascript 主干集合:迭代&;有效搜索,javascript,backbone.js,Javascript,Backbone.js,我所拥有的:我正在编写我非常琐碎的媒体播放器。所以在它的某个地方我收集了一些字幕(比如说每部电影大约有2000个)。所以每个字幕看起来像: Object { id: "1" startTime: 2468 endTime: 4743 text: "Test subtitle." } 我想要:非常有效地做两件事: .next()方法,该方法将为我获取下一个副标题 .getByTime(neededTime)以有效的方式对整个字幕集进行类似于二进制搜索的搜索。关键是neededTi
Object {
id: "1"
startTime: 2468
endTime: 4743
text: "Test subtitle."
}
我想要:非常有效地做两件事:
.next()
方法,该方法将为我获取下一个副标题李>
.getByTime(neededTime)
以有效的方式对整个字幕集进行类似于二进制搜索的搜索。关键是neededTime
可能介于startTime
和endTime
属性之间(即3000)问题:我将在字幕中使用主干集,但它将如何处理这两个要求?我的意思是,也许手动实现迭代器模式和二进制搜索更好?不知道这是否是最佳解决方案,但我以以下内容结束:
if (!Number.isInteger) {
Number.isInteger = function isInteger (nVal) {
return typeof nVal === "number" && isFinite(nVal) && nVal > -9007199254740992 && nVal < 9007199254740992 && Math.floor(nVal) === nVal;
};
}
/**
* Model
*/
var Subtitle = Backbone.Model.extend({
defaults: {
'startTime': '',
'endTime': '',
'text': ''
},
validate: function(attrs) {
if (!this.get('startTime')) return 'You missed startTime';
if (!this.get('endTime')) return 'You missed endTime';
if (!this.get('text')) return 'You missed text';
if (this.get('startTime') > this.get('endTime')) return 'startTime cannot be greater than endTime';
},
/**
* Compare two time periods
* @param that Subtitle with which we compare the current one
* @returns {number} positive if {@code this} is greater than {@code that}, negative if {@code this} is less than {@code that}
* and zero if they are equals or overlaps or one time period contains another.
*/
equals: function(that) {
if (!(that instanceof Subtitle)) throw Error('Cannot compare with element that does not belong to Subtitle type');
if (this.get('startTime') > that.get('endTime')) return 1;
else if (that.get('startTime') > this.get('endTime')) return -1;
else return 0;
},
/**
*
* @param moment moment for which we need to find a time period
* @returns {number} positive if {@code moment} belongs to time period greater than {@code this},
* negative if {@code moment} belongs to time period less than {@code this}
* and zero if the curect time period contain the {@code moment}.
*/
containMoment: function(moment) {
if (!Number.isInteger(moment)) throw Error('Moment should be an Integer');
if (moment >= this.get('startTime') && moment <= this.get('endTime')) return 0;
else if (moment < this.get('startTime')) return -1;
else if (moment > this.get('endTime')) return +1;
else throw Error('Impossible case :-)');
}
});
/**
* Collection
*/
var Subtitles = Backbone.Collection.extend({
model: Subtitle,
index: 0,
next: function() {
return this.at(this.index++);
},
getByMoment: function(moment) {
return this._binarySearch(this.toArray(), moment);
},
_binarySearch: function(array, moment) {
'use strict';
var minIndex = 0;
var maxIndex = array.length - 1;
var currentIndex;
var currentElement;
while (minIndex <= maxIndex) {
currentIndex = (minIndex + maxIndex) / 2 | 0;
currentElement = array[currentIndex];
if (currentElement.containMoment(moment) > 0) {
minIndex = currentIndex + 1;
}
else if (currentElement.containMoment(moment) < 0) {
maxIndex = currentIndex - 1;
}
else {
return array[currentIndex];
}
}
throw Error('No subtitle for this moment');
}
});
/**
* Test
*/
var data = [
{ id: '1',
startTime: 2468,
endTime: 4743,
text: 'Here\'s little Ben nodding off.' },
{ id: '2',
startTime: 5389,
endTime: 7698,
text: 'Look at Aunt Monica\'s Little boy.' },
{ id: '3',
startTime: 7948,
endTime: 11099,
text: '-Look, he\'s got Ross\' hair cut.\n-Let me see.' },
{ id: '4',
startTime: 11948,
endTime: 14907,
text: 'Oh, God!\nIs he just the sweetest thing?' },
{ id: '5',
startTime: 15148,
endTime: 17946,
text: 'You must just want\nto kiss him all over.' }
];
var subtitles = new Subtitles();
subtitles.add(data);
var moment = 3000;
console.log(subtitles.next().attributes);
console.log(subtitles.next().attributes);
console.log(subtitles.next().attributes);
console.log(subtitles.next().attributes);
console.log(subtitles.getByMoment(moment).attributes);
if(!Number.isInteger){
Number.isInteger=函数isInteger(nVal){
nVal的返回类型==“数字”&&isFinite(nVal)&&nVal>-9007199254740992&&nVal<9007199254740992&&Math.floor(nVal)==nVal;
};
}
/**
*模型
*/
var Subtitle=Backbone.Model.extend({
默认值:{
“开始时间”:“,
“结束时间”:“,
“文本”:”
},
验证:函数(attrs){
如果(!this.get('startTime'))返回“您错过了startTime”;
如果(!this.get('endTime'))返回“您错过了endTime”;
如果(!this.get('text'))返回“您错过了文本”;
如果(this.get('startTime')>this.get('endTime'))返回“startTime不能大于endTime”;
},
/**
*比较两个时间段
*@param与当前字幕进行比较的字幕
*@如果{@code this}大于{@code that},则返回{number}正值;如果{@code this}小于{@code that},则返回负值
*如果它们相等或重叠,或者一个时间段包含另一个时间段,则为零。
*/
等于:函数(that){
if(!(Subtitle的那个实例))抛出错误('无法与不属于Subtitle类型的元素进行比较');
if(this.get('startTime')>that.get('endTime'))返回1;
否则如果(that.get('startTime')>this.get('endTime')返回-1;
否则返回0;
},
/**
*
*@param moment我们需要找到时间段的时刻
*如果{@code moment}属于大于{@code this}的时间段,则@返回{number}正值,
*如果{@code moment}属于小于{@code this}的时间段,则为负值
*如果curect时间段包含{@code moment},则为零。
*/
控制力矩:功能(力矩){
if(!Number.isInteger(矩))抛出错误('矩应该是整数');
如果(矩>=this.get('startTime')&矩this.get('endTime'))返回+1;
else抛出错误('不可能的情况:-');
}
});
/**
*收藏
*/
var Subtitles=Backbone.Collection.extend({
型号:副标题,,
索引:0,
下一步:函数(){
返回this.at(this.index++);
},
getByMoment:函数(矩){
返回此。\二进制搜索(this.toArray(),矩);
},
_二进制搜索:函数(数组、矩){
"严格使用",;
var-minIndex=0;
var maxIndex=array.length-1;
var电流指数;
无功电流元件;
while(minIndex 0){
最小索引=当前索引+1;
}
else if(currentElement.Container力矩(力矩)<0){
maxIndex=currentIndex-1;
}
否则{
返回数组[currentIndex];
}
}
抛出错误(“此时无字幕”);
}
});
/**
*试验
*/
var数据=[
{id:'1',
开始时间:2468,
完时间:4743,
文字:“小本正在打瞌睡。”,
{id:'2',
开始时间:5389,
完时间:7698,
短信:“看看莫妮卡阿姨的小男孩。”,
{id:'3',
开始时间:7948,
完时间:11099,
文字:'-看,他剪了罗斯的头发。\n-让我看看。'},
{id:'4',
起始时间:11948,
结束时间:14907,
文字:“哦,上帝!\n他是最可爱的吗?”},
{id:'5',
开始时间:15148,
结束时间:17946,
文字:“你一定是想\n吻他全身。”
];
var subtitles=新字幕();
副标题。添加(数据);
var矩=3000;
console.log(subtitles.next().attributes);
console.log(subtitles.next().attributes);
console.log(subtitles.next().attributes);
console.log(subtitles.next().attributes);
log(subtitles.getByMoment(矩).attributes);