[c#] lambda

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • ? ?
  • Registratie: Mei 2007
  • Niet online
Ik gebruik niet zoveel lambda en ben er niet echt vloeiend is, dus misschien is het een simpele vraag.
Maar hier gaat hij.

List 1 met 'wagons': (id, nr)
List 2 met 'shipments': (id, wagonnr, active)

Als resultaat wil ik een List met alle wagons, waarvan het wagonnr niet voorkomt in de List shipments met een actieve = true waarde.

Dus de wagonnr kan in List2 zitten met een active=false waarde óf de wagonnr kan er niet in voorkomen. Beiden moeten in het resultaat zitten.

Simpele lambda's lukken me wel, maar een voorzetje zou hier geapprecieerd worden.
Als tijdelijk oplossing haal ik de gegevens nog eens op uit de database met een aparte query.

Acties:
  • 0 Henk 'm!

  • Cloud
  • Registratie: November 2001
  • Laatst online: 11:02

Cloud

FP ProMod

Ex-moderatie mobster

Volgens mij bedoel je Linq of niet? :) Lambda's worden wel gebruikt bij Linq queries, althans die notatie ervan maar zijn zelf wat anders.

Verder heb ik veel gehad aan al die MSDN pagina's en aan 101 Linq Samples. Let op, de meeste samples gebruiken niet de Lambda notatie maar de variant met method chaining/fluent interface.

Veel oefenen! :)

Never attribute to malice that which can be adequately explained by stupidity. - Robert J. Hanlon
60% of the time, it works all the time. - Brian Fantana


Acties:
  • 0 Henk 'm!

  • ? ?
  • Registratie: Mei 2007
  • Niet online
Ik gebruik het liefst de mylist.Where(x => x.id == 1) vorm en dat noemt blijkbaar Lambda - net opgezocht ;-)
linq is dan weer de pseudo sql variant.

Acties:
  • +1 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
? ? schreef op donderdag 03 december 2015 @ 10:28:
Ik gebruik het liefst de mylist.Where(x => x.id == 1) vorm en dat noemt blijkbaar Lambda - net opgezocht ;-)
linq is dan weer de pseudo sql variant.
Nee. De .Where is een Extension method die in System.Linq zit; de => is de lambda operator en wat erna volgt is de lambda-expressie. De "SQL achtige notatie" zijn Query Expressions en niet veel meer dan syntactic sugar die compile-time omgezet wordt naar Standard Query Operator method calls (ook wel eens 'fluent syntax' genoemd in de volksmond, maar ik kan me niet herinneren dat MS ooit die terminologie gebezigd heeft).

[ Voor 22% gewijzigd door RobIII op 03-12-2015 10:41 ]

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


Acties:
  • 0 Henk 'm!

  • ? ?
  • Registratie: Mei 2007
  • Niet online
Aha ok dan :-)

code:
1
var result = railcars.Where(r => !(shipments.Where(x => x.active == true).Select(s => s.railcarid)).Any(l => l == r.id));


Zelf gevonden :-) Het lijkt z'n werk te doen, al zou iemand anders het misschien *ietsje* duidelijker kunnen maken? Ik kan er van leren! Er zijn vast kortere wegen.

code:
1
2
3
4
5
in 2 regels wordt het:
//eerst alle actieve ids in een lijstje
var list = (shipments.Where(x => x.active == true).Select(s => s.railcarid));
//alle railcars die waarvan het id niet in bovenstaande lijst zit
var result = railcars.Where(r => !list.Any(l => l == r.id));

[ Voor 67% gewijzigd door ? ? op 03-12-2015 10:44 ]


Acties:
  • 0 Henk 'm!

  • Cyphax
  • Registratie: November 2000
  • Laatst online: 09:22

Cyphax

Moderator LNX
? ? schreef op donderdag 03 december 2015 @ 10:42:
Aha ok dan :-)

code:
1
var result = railcars.Where(r => !(shipments.Where(x => x.active == true).Select(s => s.railcarid)).Any(l => l == r.id));
railcars.Where levert een nieuwe "lijst" (eigen een IEnumerable) op met elementen die voldoen aan de lambda (dus in dit geval alle items in railcars waarbij active op true staat).

Daarna ga je met Select aan de gang om een nieuwe IEnumerable op te bouwen die bestaat uit elementen van het type dat je in die select hebt. Met andere woorden: je selecteert een lijst met railcarid's. Dat levert een IEnumerable<int> op als het goed is. Tot slot krijg je true of false terug van Any() als één of meer van de elementen in die nieuwe lijst van integers gelijk is aan r.id.

Deze kun je trouwens verkorten denk ik; die Select heb je denk ik niet nodig.

Wacht, er staan nog haakjes omheen, daar heb ik even overheen gelezen dus wat ik hier schrijf klopt even niet. :+

Wel heb ik het vermoeden dat je 'm kunt verkorten tot:
code:
1
railcars.Where(r => !shipments.Any(s => s.Active == true && s.railcarid == r.id));

Maar dat moet je testen want ik doe het maar uit m'n hoofd. :)
Deze kan je vertalen met: geef me alle items waarbij in shipment niet het railcarid gelijk is aan het huidige id van de enumeratie (r.id) en waarbij Active op true staat. Dat komt overeen met de selectie die je zoekt, toch?

[ Voor 23% gewijzigd door Cyphax op 03-12-2015 10:54 ]

Saved by the buoyancy of citrus


Acties:
  • 0 Henk 'm!

  • Cloud
  • Registratie: November 2001
  • Laatst online: 11:02

Cloud

FP ProMod

Ex-moderatie mobster

In dit geval is dezelfde query in twee regels gewoon wat duidelijker :) Wat je eventueel kunt doen (en ook bij samples zult zien) is de nieuwe method calls op nieuwe regels plaatsen.

Dus:
C#:
1
2
var list = shipments.Where(x => x.active == true)
                    .Select(s => s.railcarid);

Is in dit geval niet indrukwekkend maar bij langere queries helpt het ook de leesbaarheid.

Never attribute to malice that which can be adequately explained by stupidity. - Robert J. Hanlon
60% of the time, it works all the time. - Brian Fantana


Acties:
  • 0 Henk 'm!

  • ? ?
  • Registratie: Mei 2007
  • Niet online
Cyphax schreef op donderdag 03 december 2015 @ 10:47:
[...]

Wel heb ik het vermoeden dat je 'm kunt verkorten tot:
code:
1
railcars.Where(r => !shipments.Any(s => s.Active == true && s.railcarid == r.id));
die werkt ook, blijft ingewikkeld voor m'n hersenen, maar dankje

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
? ? schreef op donderdag 03 december 2015 @ 10:59:
[...]

die werkt ook, blijft ingewikkeld voor m'n hersenen, maar dankje
Linq is op zijn beurt weer niet heel veel meer dan syntactic sugar voor ouwerwetse for-loopjes. Als je moeite hebt met de linq expressies dan raad ik je aan ze gewoon uit te schrijven in for...-vorm. Linq leest wel fijn en is echt wel handig als je 't een beetje beheerst, maar het is geen silver bullet ;)

Kort (en daarom misschien niet 100% accuraat maar wel begrijpbaar): Linq werkt op sets (IEnumerables to be precise) en voegt gewoon een zooi extension methods toe. Als je <array>.Where(...) doet of <list>.Where(...) doet gaat Linq gewoon voor je over die array/list heen lopen. Wat concreter:

C#:
1
2
var numbers = new int[] { 1, 2, 15, 17, 20 };
var evens = numbers.Where(n => n % 2 == 0);

n => kun je lezen als "n goes into" ofwel: de where schopt voor elk item in de lijst de expressie (n %2 == 0) een keer aan waarbij de n een item uit de lijst is. Je had natuurlijk ook x of MyNumber kunnen schrijven. Vervolgens verwacht de .Where() method een predicate; ofwel: iets dat een bool returned (dus: true == match predicate, false == geen match op predicate). Het result van de where is vervolgens weer een nieuwe IEnumerable (van hetzelfde type als je erin stopte) waarbij enkel de items overblijven die de predicate matchten.

Zonder linq te gebruiken is dit ongeveer wat er gebeurt:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        var numbers = new int[] { 1, 2, 15, 17, 20 };
        var evens = numbers.MyWhere(n => n % 2 == 0);
        var large = numbers.MyWhere(x => x >= 10);
        var all = numbers.MyWhere(n => true);

        Console.WriteLine("Evens: {0}", string.Join(",", evens));
        Console.WriteLine("Large: {0}", string.Join(",", large));
        Console.WriteLine("All  : {0}", string.Join(",", all));
    }
}

public static class MyLinq
{
    public static IEnumerable<T> MyWhere<T>(this IEnumerable<T> items, Func<T, bool> predicate)
    {
        foreach (var i in items)
            if (predicate(i))
                yield return i;
    }
}

Stap daar maar eens met je debugger doorheen; dan gaan er geheid een boel lampjes branden ;) Note ook dat de MyWhere weer een IEnumerable returned dus er is niets wat je let om een items.MyWhere(...).MyWhere(...).MyWhere(...) te doen (hoewel dat niet erg efficiënt is en je waarschijnlijk beter in je expression wat kunt &&'en en ||'en ;) ).

Linq biedt een crapton aan extensionmethods (en dan hebben we 't nog niet gehad over IQueryables, deferred execution enzovoorts en yield waar linq zwaar op leunt) maar het loont zich zéker het te leren of je er in ieder geval in te verdiepen.

[ Voor 85% gewijzigd door RobIII op 03-12-2015 11:44 ]

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


Acties:
  • 0 Henk 'm!

  • HurpDerp
  • Registratie: Oktober 2013
  • Laatst online: 18-11-2024
Cyphax schreef op donderdag 03 december 2015 @ 10:47:
[...]

Wel heb ik het vermoeden dat je 'm kunt verkorten tot:
code:
1
railcars.Where(r => !shipments.Any(s => s.Active == true && s.railcarid == r.id));
Eventueel zou je em nog verder kunnern verkorten naar:
code:
1
railcars.Where(r => !shipments.Any(s => s.Active && s.railcarid == r.id));


s.Active staat namelijk gelijk aan s.Active == true
Scheelt weer 7 karakters ;)

[ Voor 5% gewijzigd door HurpDerp op 03-12-2015 11:04 ]


Acties:
  • 0 Henk 'm!

  • Cyphax
  • Registratie: November 2000
  • Laatst online: 09:22

Cyphax

Moderator LNX
RobIII schreef op donderdag 03 december 2015 @ 11:02:
[...]

Linq is op zijn beurt weer niet heel veel meer dan syntactic sugar voor ouwerwetse for-loopjes.
Dit is wel een goede superkorte samenvatting. Het zijn vreselijk handige functies die je op collecties kunt toepassen om ze te muteren, te doorzoeken, delen van op te halen, etc. Ik zat toevallig gisteren nog in code te kijken van een collega die "gewoon" een for-loopje schreef met een integer-iterator en zelfs nog een array die werd geïnitialiseerd met als grootte de length van een andere collectie (wat dus gelijk een foutje is, die lengte zou 1 minder moeten zijn dan die length vanwege het 0-based zijn van arrays tov een length of count()). Die hele loop kan ik met 2 Linq-statements herschrijven. :)

De tijd die je steekt in Linq onder de knie krijgen win je heel snel weer terug. :)

Saved by the buoyancy of citrus


Acties:
  • 0 Henk 'm!

  • YakuzA
  • Registratie: Maart 2001
  • Niet online

YakuzA

Wat denk je nou zelluf hey :X

Het is wel handig om in de gaten te houden dat de Linq query pas wordt uitgevoerd op het moment dat je over de result collectie enumereert. (deferred execution)
Als de onderliggende collecties wijzigen voordat je het result gebruikt kan het resultaat dus anders zijn dan als je het result had gemaakt met een for loop.
http://blogs.msdn.com/b/c...9/deferred-execution.aspx

Death smiles at us all, all a man can do is smile back.
PSN


Acties:
  • 0 Henk 'm!

  • Cyphax
  • Registratie: November 2000
  • Laatst online: 09:22

Cyphax

Moderator LNX
YakuzA schreef op donderdag 03 december 2015 @ 11:57:
Het is wel handig om in de gaten te houden dat de Linq query pas wordt uitgevoerd op het moment dat je over de result collectie enumereert. (deferred execution)
Maar dat is een belangrijk verschil tussen IEnumerable<> (of IQueryable<>) en IList<>, toch? Dat heeft niet zoveel te maken met Linq an sich volgens mij?

Saved by the buoyancy of citrus


Acties:
  • 0 Henk 'm!

  • YakuzA
  • Registratie: Maart 2001
  • Niet online

YakuzA

Wat denk je nou zelluf hey :X

Cyphax schreef op donderdag 03 december 2015 @ 12:01:
[...]

Maar dat is een belangrijk verschil tussen IEnumerable<> (of IQueryable<>) en IList<>, toch? Dat heeft niet zoveel te maken met Linq an sich volgens mij?
Ja en nee :)
Ja, deferred execution kan alleen als je return type IEnumerable implementeerd.
Nee, de IEnumerable interface implementeren betekent alleen dat je een enumerator moet aanbieden.

IList implementeerd ook IEnumerable:
public interface IList : ICollection, IEnumerable

Death smiles at us all, all a man can do is smile back.
PSN


Acties:
  • 0 Henk 'm!

  • AlphaRomeo
  • Registratie: Maart 2007
  • Laatst online: 11:26

AlphaRomeo

FP PowerMod
Ik weet niet hoe groot de lijsten zijn waar je over enumereert, maar het kan zijn dat het handig is om vooraf shipments naar een dictionary om te zetten op key railcartid zodat je ze er sneller uit kunt pakken zonder eerst over de hele lijst heen te hoeven fietsen.

Acties:
  • 0 Henk 'm!

  • Haan
  • Registratie: Februari 2004
  • Laatst online: 11:03

Haan

dotnetter

YakuzA schreef op donderdag 03 december 2015 @ 11:57:
Het is wel handig om in de gaten te houden dat de Linq query pas wordt uitgevoerd op het moment dat je over de result collectie enumereert. (deferred execution)
Als de onderliggende collecties wijzigen voordat je het result gebruikt kan het resultaat dus anders zijn dan als je het result had gemaakt met een for loop.
http://blogs.msdn.com/b/c...9/deferred-execution.aspx
Hier kan je niks over zeggen, want je weet niet hoe de code van de TS er precies uitziet. Je weet niet hoe de lijsten tot stand komen, of dat überhaupt met een LINQ query uit de database gehaald wordt, en of er niet al een ToList() gedaan wordt.
Dus leuk om te noemen, maar ik denk dat het voor de TS hiermee alleen maar voor meer verwarring zorgt.

Kater? Eerst water, de rest komt later


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Haan schreef op donderdag 03 december 2015 @ 13:18:
of dat überhaupt met een LINQ query uit de database gehaald wordt
Heeft niets met een database te maken; bovenstaand voorbeeld dat ik postte doet ook gewoon aan deferred execution ;) Maar eens dat 't allemaal alleen maar voor verwarring zorgt ;)
Note: Deferred execution applies to all varieties of LINQ, including LINQ to SQL, LINQ to Objects and LINQ to XML. However, of the three, it is only LINQ to SQL that returns an expression tree by default. Or more specifically, it returns an instance of the IQueryable interface that references an expression tree...

[ Voor 35% gewijzigd door RobIII op 03-12-2015 14:02 ]

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


Acties:
  • 0 Henk 'm!

  • RayNbow
  • Registratie: Maart 2003
  • Laatst online: 10:51

RayNbow

Kirika <3

RobIII schreef op donderdag 03 december 2015 @ 11:02:
[...]

Linq is op zijn beurt weer niet heel veel meer dan syntactic sugar voor ouwerwetse for-loopjes.
Al gaat die vlieger niet helemaal op voor bijv. niet-enumereerbare dingen.

Ipsa Scientia Potestas Est
NNID: ShinNoNoir

Pagina: 1