在我的应用程序中,我在前端有一个非常大的对象数组,这些对象在[" object_id"]标题下都有一些长ID。我使用UnderscoreJS来处理这个列表的所有操作。这是一个应用程序的原型,最终将在后端处理大部分工作。
合并列表是应用程序要求的重要组成部分。请参阅,我最初使用的列表将具有许多具有相同object_id的不同对象。最初我将它们与groupBy和map-reduce一起合并,但现在需求已经改变,我将它们一次合并(大约一秒钟,模拟一个输入流)到最初为空的数组。
我天真的实现是这样的:
function(newObject, objects) {
var obj_id = newObject["object_id"]; //id of object to merge, let's say
var tempObject = null;
var objectToMerge = _.find(objects,
function(obj) {
return obj_id == obj["object_id"];
});
if (objectToMerge) {
tempObject = merge(objectToMerge, newObject);
objects = _.reject(objects, /*same function as findWhere*/ );
} else {
tempObject = newObject;
}
objects.push(tempObject);
return objects;
}
当我从模拟数据" source"中重新出现时,这比以前更加高效。每次推送一个新对象的数组,所以它从我认为的O(N ^ 2)至少减少到O(N),但是这里的N是如此之大(对于JavaScript来说,无论如何!我想优化它。目前最糟糕的情况是,object_id不是多余的,整个列表遍历两次。所以我喜欢做的是查找和替换,这个操作会返回一个新版本的列表,但是用合并的对象代替旧版本。
我可以做一个迭代器返回一个新的合并对象的地图,如果object_id是相同的,但是没有_.find有的短路评估,这意味着有一个最糟糕的运行时并将其作为默认运行时,并且如果没有匹配则不会轻易地推送对象。
我也希望避免将原始数组变异。我知道objects.push(tempObject)做了那件事,但出于数据绑定的原因,我忽略了这一点,并将变异列表作为新内容返回。
我也不可避免地要检查数组以查看新对象是否已合并或是否已附加。使用闭包我可以跟踪一个标志,看看合并是否发生了,但我试图尽可能地为了自己的理智而习惯性地LISPy。此外,超过某一点,大多数对象将被合并,因此添加新项目的额外运行时间不是一个巨大的问题,只要它只在必须发生时才会发生。