在计算列上运行总计

时间:2011-03-02 03:26:27

标签: linq linq-to-sql

如何在结果1中计算的列绿色的结果2中获得运行总计1.下面的代码未产生所需的结果。感谢。

num running_total
-----------------

0   True 
0   True 
0   True 
0   True 
0   True 
0   True 
0   True 
1   False 
1   False 
1   False 
1   False 
1   False 
0   True 
1   False 
1   False 
1   False


 Sub Main

    Dim runT1 As integer

    Dim results1= //some code

    Dim results2=
    From v in results1
    Select New With {.num = v.green, .running_total = (runT1 = runT1 + v.green)}

    results2.dump()

 End Sub

2 个答案:

答案 0 :(得分:2)

使用基于linq的方法有很多方法可以解决这个问题。

如果您正在使用VB.NET 4.0,那么您可以使用多行lambda,这将为您提供最接近您尝试的解决方案:

Dim runningTotal = 0
Dim getRunningTotal As Func(Of Integer, Integer) = Function(n)
    runningTotal += n
    Return runningTotal
End Function

Dim results2 =
    From v In results1
    Select New With { .num = v.green, .running_total = getRunningTotal(v.green) }

这种方法的问题在于,如果您多次评估result2查询,则会复合运行总计(即从上次开始计算)。无论如何,你的代码中也会发生同样的情况。

在C#中,我会使用迭代器创建一个扩展方法,但是在这个时候VB.NET不支持迭代器函数,所以我们必须选择一些更有趣的方法。

第一种是使用Aggregate& Zip扩展方法:

Dim results2 =
    results1.Zip(
        results1.Aggregate(
            New Integer() { },
            Function(tt, t) _
                tt.Concat(New Integer() { tt.LastOrDefault() + t.green }).ToArray()
        ),
            Function (r1, rt) New With { .num = r1.green, .running_total = rt }
    )

是的,它确实有效,但它并不过分高效,因为它需要为源集合中的每个元素构建连续的中间数组。

最后一种方法是使用Microsoft的Rx团队生成的Scan库提供的System.Interactive扩展方法。 Scan的工作方式与Aggregate类似,但会自动生成中间值,因此效率更高。

Dim results2 =
    results1.Scan(
        New With { .num = 0, .running_total = 0 },
        Function (tt, t) _
            New With { .num = t.green, .running_total = tt.running_total + t.green }
    )

或者:

Dim results2 =
    results1.Zip(
        results1.Scan(0, Function(tt, t) tt + t.green),
        Function (r1, rt) New With { .num = r1.green, .running_total = rt }
    )

简单,是吗?

答案 1 :(得分:0)

自问这个问题已经有一段时间了,你现在可能已经解决了这个问题,但是,以防万一......

我怀疑你的问题实际上是VB使用“=”进行布尔比较和分配。

你在哪里:

.running_total = (runT1 = runT1 + v.green)

VB将其视为与C#代码相同的内容:

.running_total = (runT1 == (runT1 + v.green))

我在相当长的一段时间内没有使用VB.net,但是,如果支持+ =运算符,请尝试使用它,即

.running_total = (runT1 += v.green)