[VB.Net] Linq en Lambda

Pagina: 1
Acties:

Onderwerpen


  • Jay-P
  • Registratie: Oktober 2003
  • Laatst online: 04-06 00:39
Stel ik heb de volgende oplopende data:

Index:Hits:
010
115
225
345
......


En ik wil hier graag de verschillen in plaats van de totalen terug krijgen:

Index:Hits:
010
15
210
320
......


Nu doe ik dat dus vrij omslachtig met extra properties en een for ... next loop. Dit wil ik graag versimpelen door er een linq expressie tegen aan te gooien. Nu heb ik dus de volgende linq expressie maar die geeft bij mij een syntax error (in LinqPad omdat ik probeer Linq wat meer onder de knie te krijgen en LinqPad een stuk makkelijker 'schetst' dan in VS). Iemand een idee wat ik fout doe ?


Visual Basic .NET:
1
2
(From d in Stats Select d).tolist().Select(Function(d, index) New With {.Index = index, _
.Hits = d.Hits, .HitsRelative = iif(index = 0, 0, (d.Hits - d.Hits(index -1)))})


DeHet anonymous object werkt gewoon als ik ".HitsRelative = iif(index = 0, 0, (d.Hits - d.Hits(index -1))" weghaal. Hier doe ik dus iets fout maar ik zou niet weten wat ?

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • Jay-P
  • Registratie: Oktober 2003
  • Laatst online: 04-06 00:39
Ja, precies dat idee, alleen dan in VB.NET. Als ik bijvoorbeeld het volgende doe:

Visual Basic .NET:
1
(From d in Stats Select d.Hits).tolist().Select(Function(d, index) New With {.Index = index, .Hits = d, .HitsRelative = d - d})


Krijg ik keurig:

0100
1150
.........


Ik begrijp alleen niet waarom ik niet "d - d(index - 1)" kan doen zoals ik al meerdere voorbeelden van in C# heb gezien. (heb voor het debuggen even de iif statement weggelaten).

  • pedorus
  • Registratie: Januari 2008
  • Niet online
De c#-voorbeelden gebruik functies als Zip, of maken gebruik van indices, dat lukt niet in jouw voorbeeldcode omdat de list niet eens een naam heeft om naar terug te verwijzen. Ik zit me eigenlijk af te vragen waarom er niet een semi-linq oplossing wordt voorgesteld (nadeel: niet te paralleliseren):
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
Dim list = {10, 15, 25, 45}

Dim previous = 0
Dim result = list.Select( _
    Function(d, index)
        Dim relative = d - previous
        previous = d
        Return New With {.Index = index, .Hits = d, .HitsRelative = relative}
    End Function)

Ter vergelijking ongeveer de oplossingen van SO:
Visual Basic:
1
2
3
4
5
6
7
8
Dim result2 = Enumerable.Range(0, list.Length()).Select( _
    Function(i) New With {.Index = i, .Hits = list(i), _
        .HitsRelative = list(i) - If(i > 0, list(i - 1), 0)})

Dim result3 = {0}.Union(list).Zip(list, _
    Function(prev, cur) New With {.Hits = cur, .HitsRelative = cur - prev}) 
    ' .Index is missing and can be added with extra select
    'Possible problem if dummy element is more complex than '0'

De vraag is nu natuurlijk wat het beste is. Ik zou het hele linq laten zitten en gewoon een for-loopje gebruiken om het lijstje te vullen, en dat heb je geloof ik al ;)



Om trouwens terug te komen op de initiële vraag: er staat een "i" teveel waardoor je een index out of bounds exception krijgt en je wil waarschijnlijk Stats(index - 1).Hits en niet d.Hits(index-1) ;)

[ Voor 7% gewijzigd door pedorus op 15-09-2012 17:14 ]

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


  • Jay-P
  • Registratie: Oktober 2003
  • Laatst online: 04-06 00:39
De reden dat ik een Linq oplossing zoek is eigenlijk primair om Linq (en specifiek de combinatie met Lambda's) beter te leren kennen maar ook omdat ik op het moment een stuk of 20 "Hits" heb (zeg, HitsA, HitsB, HitsC ..... etc.) waarvan dus allemaal in de loop het verschil berekent moet worden, wat niet echt een probleem is, maar waarvoor ik ook dus voor elke property één extra aan moet maken die niet het totaal maar het verschil tov de vorige weergeeft. Ik geef nl. het hele object door aan een grafiek die een valuemember nodig heeft om die cijfers te visualiseren. Het is dus eigenlijk ook gewoon een software ontwerp probleem even afgezien van de Linq kwestie. Ik ga nog even nadenken over welke mogelijkheden ik nog meer heb om dit probleem te tackelen (misschien een custom Linq operator implementeren, het object dupliceren en alle HitsX daar overheen gooien)

Overigens was het originele C# voorbeeld wat ik had gevonden het ongeveer volgende(kan de originele ff niet meer vinden):

C#:
1
2
3
var LinqList = list.Select((myObject, index) => 
new {ID = myObject.ID, Date = myObject.Date, Value = myObject.Value, 
DiffToPrev = (index > 0 ? myObject.Value - list[index - 1].Value : 0)});
pedorus schreef op zaterdag 15 september 2012 @ 17:06:
Om trouwens terug te komen op de initiële vraag: er staat een "i" teveel waardoor je een index out of bounds exception krijgt en je wil waarschijnlijk Stats(index - 1).Hits en niet d.Hits(index-1) ;)
Klopt en klopt (even voor de bevestiging, je doelt op de iif omdat die de hele zooi evalueert itt tot een if waarbij de true/false statement pas na de if 'controle' wordt geevalueerd, right ?, Ik dacht alleen dat VB de if op jouw manier niet ondersteunt itt tot c# ?)

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Klopt, en If(...,...,...) wordt natuurlijk inmiddels wel ondersteund in VB, ander dan zou het niet werken ;)

20 keer dezelfde code programmeren lijkt me in ieder geval niet de bedoeling. Ik weet ook niet of er hele objecten voor de grafiek nodig zijn bijvoorbeeld, dus het is wat lastig te bepalen wat wel handig is..

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten

Pagina: 1