2013-09-06 9 views
7

I 2 Liste Objekt vom Typ einer Klasse haben,Wie lokale Variablen in einem Lambda-Ausdruck verwenden

class person 
    { 
     public string id { get; set; } 
     public string name { get; set; } 
    } 

List<person> pr = new List<person>(); 
pr.Add(new person { id = "2", name = "rezoan" }); 
pr.Add(new person { id = "5", name = "marman" }); 
pr.Add(new person { id = "3", name = "prithibi" }); 

List<person> tem = new List<person>(); 
tem.Add(new person { id = "1", name = "rezoan" }); 
tem.Add(new person { id = "2", name = "marman" }); 
tem.Add(new person { id = "1", name = "reja" }); 
tem.Add(new person { id = "3", name = "prithibi" }); 
tem.Add(new person { id = "3", name = "prithibi" }); 

Jetzt muss ich alle IDs von „pr“ Listobject erhalten, die keinen Eintrag hat oder ungerade Anzahl der Einträge in der "tem" ListObejct. mit Lamda.

Um dies zu tun, habe ich verwendet,

HashSet<string> inconsistantIDs = new HashSet<string>(pr.Select(p => p.id).Where(p => tem.FindAll(t => t.id == p).Count == 0 || tem.FindAll(t => t.id == p).Count % 2 != 0)); 

und es funktioniert gut.

aber man kann aus dem Code siehe i tem.FindAll (t => t.id == p) .Count zweimal verwendet haben, mit == 0 und % 2! = 0 bis comapre.

Gibt es eine Möglichkeit tem.FindAll zu verwenden (t => t.id == p) .Count einmal und speichern es zu einer temporären Variablen und dann vergleichen Sie diese Variable mit == 0 und % 2! = 0.

Einfacher möchte ich es nur einmal für zwei Bedingung hier verwenden.

+0

Bitte nicht subjjects als „facing Ausgabe verwenden in xxx ", das wird der Google-Link sein. –

+0

Haben Sie @TimSchmelter – Rezoan

Antwort

14

Use a statement lambda instead of an expression lambda

var inconsistantIDs = new HashSet<string>(
      pr.Select(p => p.id).Where(p => 
        { 
        var count = tem.FindAll(t => t.id == p).Count; 
        return count == 0 || count % 2 != 0; 
        } 
      )); 
+0

Ya das funktioniert. aber "count .Count% 2! = 0" sollte "count% 2! = 0" sein. Könntest du es bitte einfach korrigieren? @Ahmed KRAIEM – Rezoan

+3

Anstelle von 'FindAll' würde ich' Count() 'verwenden. Ersteres muss für jede Person eine neue Sammlung erstellen. –

+0

@Rezoan Korrigiert. @Tim Das stimmt. 'var count = tem.Count (t => t.id == p);' –

2
HashSet<string> inconsistantIDs = new HashSet<string>(
    pr.Select(p => new { Id = p.id, Cnt = tem.FindAll(t => t.id == p.id).Count() }) 
     .Where(p => p.Cnt == 0 || p.Cnt % 2 != 0) 
     .Select(p => p.Id); 
+0

Danke, aber es gibt mir Fehler auf "t.id == p" und ".Count()" sollte ".Count" sein. Könnten Sie bitte dieses Problem sehen? – Rezoan

+0

behoben. Aber ich würde diesen Code nicht verwenden, wenn Sie ihn nicht verstehen. –

4

Vielleicht einfach:

var query = pr.Where(p => { int c = tem.Count(p2 => p.id == p2.id); return c == 0 || c % 2 != 0; }); 

kehrt zwei Personen:

2 "rezoan" 
5 "marman" 
2

Auf einer Seite zur Kenntnis, streng leistungsmäßig würden Sie eine bessere Leistung erzielen, wenn Sie eine Hash-Zuordnung jeder ID zu ihrer Zählung erstellen und sie dann in einer Schleife durchsuchen.

Gerade jetzt haben Sie einen O(n*m)-Algorithmus, der auf O(n+m) reduziert würde:

// create a map (id -> count), O(m) operation 
var dictionary = new Dictionary<string, int>(); 
foreach (var p in tem) 
{ 
    var counter = 0; 
    dictionary.TryGetValue(p.id, out counter); 
    counter++; 
    dictionary[p.id] = counter; 
} 

// search the map, O(n) operation 
var results = new HashSet<string>(); 
foreach (var p in pr) 
{ 
    var counter = 0; 
    dictionary.TryGetValue(p.id, out counter); 
    if (counter == 0 || counter % 2 != 0) 
     results.Add(p.id); 
} 
+0

Danke für Ihre wertvollen Informationen.+1 @Groo – Rezoan

3

Neben Aussage Lambda können Sie verwenden let clause:

HashSet<string> inconsistantIDs = new HashSet<string>(
    from p in pr 
    let count = tem.FindAll(t => t.id == p).Count 
    where count == 0 || count % 2 != 0 
    select p.id 
);