Промежуточный итог по вычисляемому столбцу - PullRequest
0 голосов
/ 02 марта 2011

Как я могу получить running_total в результатах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 ]

2 голосов
/ 03 августа 2011

Существует несколько способов решения этой проблемы с использованием подхода на основе linq.

Если вы используете VB.NET 4.0, вы можете использовать многострочные лямбда-выражения, которые дадут вам наиболее близкое решениек тому, что вы пытались:

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 }
    )

Да, это работает, но не слишком эффективнотак как он должен создавать последовательные промежуточные массивы для каждого элемента в исходной коллекции.

Последний подход заключается в использовании метода расширения Scan, доступного из библиотеки System.Interactive, созданной командой Rx в Microsoft.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 }
    )

Просто, да?

0 голосов
/ 03 августа 2011

Прошло много времени с тех пор, как этот вопрос был задан, и вы, возможно, уже решили это, но на всякий случай ...

Я подозреваю, что ваша проблема в том, что VB использует "=" как для логического сравнения, так и для присваивания.

Где у вас есть:

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

VB обрабатывает его так же, как код C #, который гласит:

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

Я давно не пользовался VB.net, но, если поддерживается оператор + =, попробуйте использовать его вместо этого, т.е.

.running_total = (runT1 += v.green)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...