Javascript 如何在具有范围的集合之间快速分配值

Javascript 如何在具有范围的集合之间快速分配值,javascript,algorithm,collections,lodash,Javascript,Algorithm,Collections,Lodash,使用lodash和javascript。我有两个集合,我试图将其中一个集合的值分布到另一个集合中它们的关联范围。下面展示了我在如何处理这种情况方面的最佳尝试,但很快就遇到了我学到的所谓“时间问题”。对于我的函数,一旦我开始获取大于大约20个值的数组,这个函数将花费大量的时间 我怎样才能做得更快?关于如何以线性方式实现这一点,有什么想法吗 var colA = [ {point: 3, value: 5}, {point: 10, value: 8}, {point: 6,

使用lodash和javascript。我有两个集合,我试图将其中一个集合的值分布到另一个集合中它们的关联范围。下面展示了我在如何处理这种情况方面的最佳尝试,但很快就遇到了我学到的所谓“时间问题”。对于我的函数,一旦我开始获取大于大约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;
        }
    });
}); 

注意:此函数已从当前形式大大简化。这是我试图做的基本理论的代表。

假设值是整数,范围是合理的(不要太大)

定义从0到x的所有值之和。要计算它,请从
colA
开始。对于值
colA[i]
->求和[colA[i]+=colA[i]。然后运行槽总和,将所有内容相加,使其与定义匹配

现在对于colB中的每个元素,
value=sums[max-1]-sums[min-1]
。(-1,因为边界上的条件)

所以现在你是O(范围+可乐+可乐)(或3的最大值)


如果范围很大,您仍然可以执行相同的操作,但首先要规范化值。也就是说,获取colA、colB.min和colB.max sort中的所有值,删除重复项,并用排序数组中的索引替换它们。这对计算来说应该无关紧要,但范围变成了与colA+colB大小一样大的整数。

不确定这是否具有更好的时间复杂度,但它更“洛达什”:

\映射(colB,函数(b){
返回{value:}(colA).filter(函数(a){
返回a.point>=b.min&&a.point
  • 返回带有新对象的新数组(无副作用)
  • 用于从
    colB
    向对象分配新的
  • colA
    中查找适合当前
    colB
    对象的对象
  • 根据
    属性计算总和

用于排序数组和非重叠范围的解决方案,显然不适用于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}];
sort(函数(k,l){返回k.point-l.point;});
排序(函数(k,l){返回k.min-l.min | | k.max-l.max;});
可乐减少(功能(i,aa){
而(icolB[i].max){
i++;
}

if(colB[i]&&colB[i].min输出应该是什么样的?您可以对colA进行排序,然后通过二进制搜索找到每个colB范围内的值-这不是线性的,而是一种改进这是二次的,但我很惊讶,在今天这个时代,它只需要“大于20个值”就可以了“此功能需要相当长的时间。"此设置中的函数调用是否涉及大量开销?感谢您的提问-我添加了一些细节,希望能够澄清发生了什么。@AakashM是的,此函数中有大量开销。如以下注释所述,这是实际发生的情况的超级简化版本-我已尝试剥离这是我试图解决的关键问题。好吧,你的答案似乎有潜在的适用性,但我觉得自己很傻,因为我很难遵循逻辑。你介意写一个代码的示例吗?另外,根据你的假设-可以安全地假设值是整数,但不是假设范围不是太大。我实际上处理的是UTC时间戳值,范围实际上可能相当大。如果使用时间戳,则进行规范化。我对javascript不太在行。你应该有一个向量和,最初看起来像0、0、0、5、0、0、18、2、12、0、8(基于点肯定更大)“洛达斯"!然而,正如你所建议的,可能是这样的-它没有更好的时间复杂度…这工作非常完美!正是我所寻找的。我在OP中编写的函数花了将近5秒的时间迭代了50次。但对于这个版本,它只花了不到250ms的时间。事实上,我不得不将它推到100秒以上,然后我才开始看到一个可测量的结果折痕。非常感谢!
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}
];
_.map(colB, function(b) { 
    return _.defaults({ value: _(colA).filter(function(a) { 
        return a.point >= b.min && a.point < b.max; 
    }).sumBy('value') }, b);
});