2009-06-13 4 views
9

hinzu Ich habe eine Auflistung von Objekten eines Typs, die ich in einen anderen Typ konvertieren möchte. Das kann mit foreach leicht gemacht werden, aber ich würde gerne herausfinden, wie man die Aggregatfunktion von Linq dazu benutzt.So fügen Sie zu einer Liste mithilfe der Aggregatfunktion von Linq C#

Das Problem ist alle Aggregat Beispiele verwenden Typen Zeile Zeichenfolge oder int, die den Operator '+' unterstützen. Ich möchte, dass der Akkumulatortyp eine Liste ist, die keine '+' Semantik unterstützt.

Hier ist ein kurzes Beispiel:

public class DestinationType 
{ 
    public DestinationType(int A, int B, int C) { ... } 
} 

var set = from item in context.Items 
      select new { item.A, item.B, item.C }; 

var newSet = set.Aggregate(new List<DestinationType>(), 
          (list, item) => list.Add(new DestinationType(item.A, item.B, item.C))); 

Das Problem ist, dass Liste <> .Add void zurückgibt. Der Rückgabetyp des zweiten Aggregationsparameters muss eine List sein.

Wenn ich eine Liste Art hatte, die ‚+‘ Typ Semantik unterstützt konnte ich nur den zweiten Parameter machen

list + item 

Jedoch habe ich keine Sammlung Art finden können, die diese Art der Sache unterstützt.

Scheint, wie dies in Linq leicht möglich sein sollte. Gibt es einen Weg? Außerdem, wenn mir ein ganz einfacher Weg fehlt, würde ich gerne darüber auch lernen. Vielen Dank!

+0

Danke für alle großen Antworten! Sam & Talljoes Antworten erreichten dies am einfachsten mit Linq. Danke nochmal! – Slaggg

Antwort

9

Ich denke, ein Anruf an Select kombiniert mit ToList() könnte sein, was Sie hier brauchen. Zum Beispiel:

context.Items 
    .Select(item => new DestinationType(item.A, item.B, item.C)) 
    .ToList(); 
23

Unter der Annahme, diese LINQ to Objects ist, versuchen ...

var newSet = set.Aggregate(new List<DestinationType>(), 
            (list, item) => 
            { 
             list.Add(new DestinationType(item.A, item.B, item.C)); 
             return list; 
            }); 
+0

Dies ist der richtige Weg, es zu tun. – mquander

+0

Dies funktionierte auch bei der Verwendung von Union im Func-Teil –

4

Sie können select hier nur anwenden.

var newSet = set.Select(item => new DestinationType(...)).ToList(); 

Aggregate (allgemein als fold oder reduce bekannt) an verwendet Elemente miteinander zu verknüpfen, wo select auf jedes Element eine Funktion gilt.

Ex:

Let f eine einstellige Funktion sein, dann [a, b, c].select(f)[f(a), f(b), f(c)] entspricht.

Let f eine binäre Funktion sein, dann [a, b, c].aggregate(f, init)f(a, f(b, f(c, init))) entspricht.

Die Art und Weise Sie in Ihrem Beispiel gewählt hat, ist in C# selten, aber oft in der funktionalen Programmierung verwendet, in denen (verlinkt) Listen in neue Listen umgewandelt werden, statt eine bestehende Sammlung ändern:

reversed = fold (\list element -> element:list) [] [1..10] 

Wenn Sie wirklich wollen Führen Sie diese Berechnung mit aggregate durch, verwenden Sie Dustins Lösung oder implementieren Sie besser einen Linked-List-basierten Typ für unveränderbare Sammlungen (Sie können diesem Typ sogar eine operator + geben).

3
list.AddRange(context.Items.Select(item => 
    new DestinationType(item.A, item.B, item.C)); 

Ich weiß, es nicht die Aggregate-Funktion nicht verwenden, aber man sollte wahrscheinlich ein besseres Beispiel zu verwenden, um das Aggregat zu lernen finden.

1

Es sei denn, ich bin etwas offensichtlich fehlt, warum nicht nur:

public class DestinationType 
{ 
    public DestinationType(int A, int B, int C) { ... } 
} 

var newSet = from item in context.Items 
    select new DestinationType(item.A, item.B, item.C); 
Verwandte Themen