2016-08-18 2 views
2

Ich versuche, eine partielle Liste von Entitäten für eine Liste von Entitäten durch ihre Guids zu erhalten.Holen Sie sich eine Liste von Entitäten nach Liste von Guids

List<Entity> GetEntitiesByGuids (List<Entity> entities, List<Guids> guids) 
{ 
    List<Entities> retVal = new List<Entities>(); 
    foreach(var guid in guids) 
    { 
     var Entity = Entities.Find(e=>e.Guid ==guid) 
     retVal.Add(Entity); 
    } 
return retVal; 
} 

Gibt es eine schöne Möglichkeit, es zu tun, ohne foreach:

kann erreicht werden durch?

Antwort

3

Performance-weise die beste Art der Filterliste gegen eine andere Liste ist Hash-Sammlungen zu verwenden, da mit Hash wir schnelles Nachschlagen haben (das hat die Komplexität von fast O (1))

lassen Sie uns zunächst Zeit messen, benötigt durch normale List<Guid> von Hashes mit:

public static List<Entity> GetEntitiesByGuids(List<Entity> entities, List<Guid> guids) 
{ 
    return entities?.Where(e => guids.Contains(e.Guid)).ToList(); 
} 

Und Main() Verfahren ist in beiden Fällen:

var entities = new List<Entity>(); 
var guids = new List<Guid>(); 

for (int i = 0; i < 100000; i++) guids.Add(Guid.NewGuid()); 

for (int i = 0; i < 100000; i++) entities.Add(new Entity() {Guid = guids[i]}); 

var guidsToFilter = guids.Skip(12000).Take(40000).ToList(); 

Console.WriteLine("Started to filter list"); 

var s = new Stopwatch(); s.Start(); 

var result = GetEntitiesByGuids(entities, guidsToFilter); 

s.Stop(); 

Console.WriteLine(s.ElapsedMilliseconds+"ms"); 

Ergebnis: 19823ms

des Jetzt HashSet<T> Sammlung einführen lassen:

public static List<Entity> GetEntitiesByGuids(List<Entity> entities, List<Guid> guids) 
{ 
    var hashedGuids = new HashSet<Guid>(guids);   
    return entities?.Where(e => hashedGuids.Contains(e.Guid)).ToList(); 
} 

Ergebnis: 11ms

+1

Danke für diese Technik! Gibt es einen performance-orientierten Überblick über Framework-Sammlungen, die Sie vorschlagen können? –

+1

Nun, Sie können lesen [this] (http://geekswithblogs.net/BlackRabbitCoder/archive/2011/06/16/c.net-grundlagen-choosing-the-right-collection-class.aspx) und [dies] (http://cc.davelozinski.com/c-sharp/fastest-collection-for-string-lookups) Artikel, wenn Sie interessiert sind. Es sind nur die ersten beiden, die bei der Google-Suche gezeigt wurden, also gibt es viele gute Sachen über die Angelegenheit. – Fabjan

+0

So cool, Danke für die ausführliche Antwort. – tal

2
List<Entity> GetEntitiesByGuids (List<Entity> entities, List<Guids> guids) 
{ 
    List<Entities> retVal = entities.Where(e => guids.Contains(e.Guid)).ToList(); 
    return retVal; 
} 
+1

Dadurch werden die Ergebnisse zurück in eine andere Reihenfolge als die Frage – Hogan

+1

achten Sie auf 'entities.Where (e => ...' Tippfehler und 'EntityList entities' anstelle von' List entities' –

+0

Dank @Vadim Levkovsky, behoben. – serhiyb

3

Es gibt auch eine schöne Möglichkeit, es mit foreach tun:

IEnumerable<Entity> GetEntitiesByGuids (EntityList entities, List<Guids> guids) 
{ 
    foreach(var guid in guids) 
    { 
     yield return Entities.Find(e=>e.Guid ==guid); 
    } 
} 
+0

Was ist besonders "nett"? – Maarten

Verwandte Themen