2009-06-13 13 views
9

Tengo una colección de objetos de un tipo que me gustaría convertir a un tipo diferente. Esto se puede hacer fácilmente con foreach, pero me gustaría descubrir cómo usar la función agregada de Linq para hacerlo.Cómo agregar a una lista usando la función agregada de Linq C#

El problema es que todos los ejemplos de agregado utilizan tipos de línea de línea o int, que admiten el operador '+'. Me gustaría que el tipo de acumulador sea una lista, que no admite la semántica '+'.

Aquí está un ejemplo rápido:

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))); 

El problema es que la lista <> .Add regresa vacía. El tipo de devolución del segundo parámetro para agregar debe ser una lista.

Si tuviera un tipo de lista que apoyó '+' semántica de tipo tan sólo pudiera hacer que el segundo parámetro

list + item 

Sin embargo no puedo encontrar ningún tipo de colección que apoya este tipo de cosas.

Parece que esto debería ser posible en Linq. ¿Hay alguna manera? Además, si me estoy perdiendo una manera completamente más fácil, me encantaría aprender sobre eso también. ¡Gracias!

+0

Gracias por todas las grandes respuestas! Las respuestas de Sam y Talljoe lograron esto de la manera más simple usando Linq. ¡Thx otra vez! – Slaggg

Respuesta

9

Creo que una llamada a Select combinada con ToList() podría ser lo que necesita aquí. Por ejemplo:

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

Asumiendo que esto es LINQ a objetos, intenta ...

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

Esta es la forma correcta de hacerlo. – mquander

+0

Esto también funcionó para mí cuando uso Union in the Func –

4

Usted sólo puede aplicarse select aquí.

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

Aggregate (generalmente conocido como fold o reduce) se utiliza para combinar elementos juntos donde select aplica una función a cada elemento.

Ex:

Let f una función unaria, entonces [a, b, c].select(f) es igual a [f(a), f(b), f(c)].

Let f una función binaria, entonces [a, b, c].aggregate(f, init) es igual a f(a, f(b, f(c, init))).

La forma en que eligió en su ejemplo es poco común en C#, pero a menudo se utiliza en la programación funcional, donde (en relación) listas se transforman en nuevas listas en lugar de cambiar una colección existente:

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

Si realmente quiere haga este cálculo con aggregate, use la solución de Dustin o mejor implemente un tipo basado en listas enlazadas para colecciones inmutables (incluso puede darle a este tipo un operator +).

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

Me di cuenta que no utiliza la función de agregado, pero probablemente debería encontrar un mejor ejemplo para aprender a utilizar el agregado.

1

A menos que me falta algo obvio, ¿por qué no hacer:

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); 
Cuestiones relacionadas