2009-04-28 1 views
0

Ich habe eine Sammlung von Objekten und bin gespannt auf die Art, wie Sie sie in zwei Listen trennen würde - eine Liste wird alles von einem bestimmten Typ, der andere wird haben der Rest. Ein Weg, ich dachte, es zu tun ist:Slickest Weg, um Objekte in separaten Listen basierend auf einem Eigenschaftswert

var typeXs = (from o in collectionOfThings where o.Type == "typeX" select o); 
var notTypeXs = (from o in collectionOfThings where o.Type != "typeX" select o); 

Die andere Möglichkeit, nur eine Schleife über collectionOfThings würde und assign basierend auf if/else.

Beide Wege sind einfach und lesbar, aber ich frage mich nur, ob es einen noch schlankeren Weg gibt?

Antwort

4

sollte dieses Beispiel zeigen, was Sie nach:

class MyObject 
{ 
    public int n; 
    public string t; 
} 

lädt meine ursprüngliche Liste nach oben:

List<MyObject> allObjects = new List<MyObject>() { 
    new MyObject() { n = 0, t = "x" }, 
    new MyObject() { n = 1, t = "y" }, 
    new MyObject() { n = 2, t = "x" }, 
    new MyObject() { n = 3, t = "y" }, 
    new MyObject() { n = 4, t = "x" } 
}; 

Split den Typen mit aus:

var typeXs = allObjects.FindAll(i => i.t == "x"); 
var notTypeXs = allObjects.FindAll(i => i.t != "x"); 

Oder

var typeXs = allObjects.Where(i => i.t == "x").ToList<MyObject>(); 
var notTypeXs = allObjects.Except(typeXs).ToList<MyObject>(); 

Alternativ könnten Sie die List.ForEach Methode verwenden, die nur einmal iteriert und daher theoretisch sollte outperform die beiden anderen Optionen. Außerdem müssen die LINQ-Bibliotheken nicht referenziert werden, was bedeutet, dass .NET 2.0 sicher ist.

var typeXs = new List<MyObject>(); 
var notTypeXs = new List<MyObject>(); 
allObjects.ForEach(i => (i.t == "x" ? typeXs : notTypeXs).Add(i)); 
+0

Das zweite Beispiel ist wahrscheinlich das beste, aber gute Arbeit, die alle Optionen gibt. +1 – BobTheBuilder

+1

Ich bevorzuge das letzte Beispiel nur für die Tatsache, dass es 2.0 sicher ist ... – BenAlabaster

+1

und es nur die Sammlung ein einziges Mal iteriert, beide anderen Optionen müssen tatsächlich die Sammlung zweimal durchlaufen, auch wenn sie vielleicht ein sind etwas eleganter geschrieben. – BenAlabaster

0
coll.GroupBy(o => o.Type == "TypeX"); 
+0

Ich bin mir nicht sicher, was ich mit dem IEnumerable tun soll >, dass es zurückgibt – JeremyWeir

1

Sie könnten den zweiten Teil umschreiben als

var notTypeXs = collectionOfThings.Except(typeXs); 
+0

Ich denke, das ist die sauberste, ausdrucksvollste Art und Weise. –

0

Ich will nicht alles über Sie ejoptimilate, aber ich denke man nur einmal Iterieren in Betracht ziehen sollten.

// You can optimize this by specifying reasonable initial capacities. 
List<TypedO> typeXs = new List<TypedO>(); 
List<TypedO> notTypeXs = new List<TypedO>(); 

foreach(TypedO o in list) 
{ 
    (o.Type == "typeX" ? typeXs : notTypeXs).Add(o); // Yeah, I know. 
} 

(korrigiert)

+0

Danke, daran hatte ich gedacht: "Der andere Weg wäre, einfach collectionOfThings zu durchlaufen und basierend auf if/else zuzuweisen." – JeremyWeir

+0

Tut mir leid, wenn ich überflüssig war. Ich musste diese Option nur empfehlen und genau genommen habe ich sie nicht verwendet.:) –

0

Wenn Sie nicht zweimal durch die Liste gehen wollen, dann:

var collectionOfThings = new[] 
     { 
      new Thing { Id = 1, Type = "typeX" }, 
      new Thing { Id = 2, Type = "typeY" }, 
      new Thing { Id = 3, Type = "typeZ" }, 
      new Thing { Id = 4, Type = "typeX" } 
     }; 


    var query = (from thing in collectionOfThings 
       group thing by thing.Type == "typeX" into grouped 
       //orderby grouped.Key descending 
       select new 
       { 
        IsTypeX = grouped.Key, 
        Items = grouped.ToList() 
       }).ToList(); 

    var typeXs = query.Find(x => x.IsTypeX).Items; 
    var notTypeXs = query.Find(x => !x.IsTypeX).Items; 
0

Ich würde die 'OfType' -Link Ausdruck verwenden, in dieser Richtung:

var typeXs = collectionOfThigs.OfType<typeX>(); 
var notTypeXs = collectionOfThings.Except(typeXs); 

(Einschließlich der .Ausnahme von einer anderen Antwort). Dies setzt voraus, dass Sie den Typ und nicht nur den Typ string haben.

Außerdem kann es eine Leistungseinbuße geben, die Entscheidung nicht nur einmal zu treffen (das if mit dem Split-Add ist wahrscheinlich der Weg, wenn es darauf ankommt), aber wenn Leistung kein Problem ist, ist Klarheit meine Präferenz.

Verwandte Themen