【发布时间】:2019-02-05 10:55:31
【问题描述】:
我有一段代码简单地遍历两个数组,对于第一个数组的每个元素,它会在第二个数组中找到相关元素,只更改第一次出现并删除剩余的元素。
/**
* The aggregation data structure:
* "_id": {
* "geometry": geometry,
* "dups": [
* "5b3b25b4e54029249c459bfc", keep only the fisrt element in allDocs
* "5b3b25b4e54029249c459e65", delete it from allDocs
* "5b3b25b4e54029249c459d7d" delete it from allDocs
* ],
* "dupsProp": [ ], array of all properties of duplicatePoints
* "count": 3
*/
var aggregationRes =[46,000 objects]
var allDocs =[345,000 objects]
aggregationRes.forEach(function (resElem, counter) {
console.log(counter + "/" + aggregationRes.length)
//Delete objects in allDocs based on dups array except the first one
var foundIndex = allDocs.findIndex(x => x._id.toString() == resElem.dups[0]);
//assign the mergedProperties
allDocs[foundIndex].properties = resElem.dupsProp;
//delete the remaining ids in Docs from dups array
resElem.dups.forEach(function (dupElem, index) {
var tmpFoundIndex = allDocs.findIndex(x => x._id.toString() == resElem.dups[index + 1]);
if (tmpFoundIndex !== -1) {
allDocs.splice(tmpFoundIndex, 1)
}
})
})
这个脚本运行了将近 4 个小时。如您所见,计算非常简单,但由于 allDocs 数组很大,因此需要很长时间。如果有人给我一个关于如何减少计算时间的提示,那就太好了。 在此先感谢
【问题讨论】:
-
使
allDocs按id索引,这样就不用每次都findIndex了。并且避免在大数组上做很多小的splices,而是将它们标记为删除,然后一次性将它们全部删除。 -
(另外:为如此大的数据使用数据库:-)
-
不要执行
x._id.toString()46K * 345K * (dupecount + 1) 次之类的操作,而是在创建一个新属性时迭代 allDocs 数组,即x._id.toString()(仅限 345K 操作)。 x._id 是整个对象吗?还是一些数字/字符串 ID? -
是否可以简单地使用
resElem.dups = [resElem.dups[0]];而不是resElem.dups.forEach迭代?您希望得到一个只包含旧数组中第一个条目的新数组,对吗?看起来很简单 -
您的聚合数据结构示例是错误的/具有误导性。看起来 _id 属性是整个内部对象。这是 node.js,您使用的是 mongodb(“javascript ObjectID”的第一个搜索结果)吗?如果是这样,可能希望将这些标签添加到您的问题中。我想有一种更有效的方法可以使用您的数据库来做到这一点。
标签: javascript arrays optimization foreach computation