使用lodash和javascript。我有两个集合,我试图将其中一个集合的值分配到另一个集合中的相关范围。我最好的尝试如下所示,如何解决这种情况,但它很快就会遇到我要学习的东西被称为" quadratic complexity"对于时间问题。对于我的函数,一旦我开始获得大于大约20个值的数组,这个函数需要花费相当多的时间。
我怎样才能更快地完成这项工作?关于如何以线性方式做到这一点的任何想法?
var colA = [
{point: 3, value: 5},
{point: 10, value: 8},
{point: 6, value: 18},
{point: 12, value: 13},
{point: 11, value: 2},
{point: 19, value: 4},
{point: 7, value: 2},
{point: 8, value: 12},
];
var colB = [
{min: 1, max: 5, value: 0},
{min: 5, max: 10, value: 0},
{min: 10, max: 15, value: 0},
{min: 15, max: 20, value: 0}
];
_.forEach(colA,function(source){
var resume = true;
_.forEach(colB,function(dest){
if(resume === true && source.point >= dest.min && source.point < dest.max){
dest.value += source.value;
resume = false;
}
});
});
====输出====
var colB = [
{min: 1, max: 5, value: 5},
{min: 5, max: 10, value: 32},
{min: 10, max: 15, value: 23},
{min: 15, max: 20, value: 4}
];
注意:此功能已从目前的形式大大简化。这代表了我试图做的基本理论。
答案 0 :(得分:1)
排序数组和非重叠范围的解决方案,显然不是lodash。
只是迭代了数组colA
。
数组colB
与正确范围的索引一起使用。在对此数组进行排序时,下一个合适的范围是在实际元素处或在以下元素处。如果索引位于数组的正确位置或末尾,则while循环结束。以下检查查看元素是否存在以及值是否大于或等于最小范围。
var colA = [{ point: 3, value: 5 }, { point: 10, value: 8 }, { point: 6, value: 18 }, { point: 12, value: 13 }, { point: 11, value: 2 }, { point: 19, value: 4 }, { point: 7, value: 2 }, { point: 8, value: 12 }, ],
colB = [{ min: 1, max: 5, value: 0 }, { min: 5, max: 10, value: 0 }, { min: 10, max: 15, value: 0 }, { min: 15, max: 20, value: 0 }];
colA.sort(function (k, l) { return k.point - l.point; });
colB.sort(function (k, l) { return k.min - l.min || k.max - l.max; });
colA.reduce(function (i, aa) {
while (i < colB.length && aa.point > colB[i].max) {
i++;
}
if (colB[i] && colB[i].min <= aa.point) {
colB[i].value += aa.value;
}
return i;
}, 0);
document.write('<pre>' + JSON.stringify(colB, 0, 4) + '</pre>');
答案 1 :(得分:0)
假设值是整数且范围合理(不太大)。
定义sums[x]
从0到x的所有值的总和。从colA
开始计算它。对于值colA[i]
- &gt; sums [colA [i]] + = colA [i]。然后运行总和并将所有内容相加以使其与定义匹配。
现在为colB中的每个元素value = sums[max - 1] - sums[min - 1]
。 (-1因为边界上的条件)。
所以现在你是O(范围+ colB + colA)(或3的最大值)。
如果范围很大,您仍然可以执行相同的操作,但首先要对值进行标准化。这是采用colA,colB.min和colB.max中的所有值排序并删除重复项,并将它们替换为已排序数组中的索引。计算结果无关紧要,但范围变为与colA + colB大小一样大的整数。
答案 2 :(得分:0)
不确定这是否有更好的时间复杂性,但它更“lodashy”:
_.map(colB, function(b) {
return _.defaults({ value: _(colA).filter(function(a) {
return a.point >= b.min && a.point < b.max;
}).sumBy('value') }, b);
});
value
从colB
分配给对象。colA
中符合当前colB
对象的对象。value
属性计算总和。