2009-10-02 23 views
23

que he visto el simple ejemplo de la función de agregado .net trabajando de esta manera:tipos complejos LINQ se agregan en una cadena

string[] words = { "one", "two", "three" }; 
var res = words.Aggregate((current, next) => current + ", " + next); 
Console.WriteLine(res); 

¿Cómo se podría utilizar la función 'agregado' si desea agregar más complejo tipos? Por ejemplo: una clase con 2 propiedades tales como 'clave' y 'valor' y desea que la salida como esta:

"MyAge: 33, MyHeight: 1.75, MyWeight:90" 

Respuesta

40

tiene dos opciones:

  1. proyecto a un string y luego agregados:

    var values = new[] { 
        new { Key = "MyAge", Value = 33.0 }, 
        new { Key = "MyHeight", Value = 1.75 }, 
        new { Key = "MyWeight", Value = 90.0 } 
    }; 
    var res1 = values.Select(x => string.Format("{0}:{1}", x.Key, x.Value)) 
           .Aggregate((current, next) => current + ", " + next); 
    Console.WriteLine(res1); 
    

    Esto tiene la ventaja de utilizar la primera string elemento como la semilla (no precede ","), pero consumirá más memoria para las cadenas creadas en el proceso.

  2. Utilice una sobrecarga agregado que acepta una semilla, tal vez un StringBuilder:

    var res2 = values.Aggregate(new StringBuilder(), 
        (current, next) => current.AppendFormat(", {0}:{1}", next.Key, next.Value), 
        sb => sb.Length > 2 ? sb.Remove(0, 2).ToString() : ""); 
    Console.WriteLine(res2); 
    

    El segundo delegado convierte nuestra StringBuilder en un string, usando el condicional para recortar la partida "".

+0

Perfecto, justo lo que estaba buscando, así que pude cronometrarlos todos, desde mis tiempos, rodando el suyo propio para el ciclo fue mucho más rápido (solo tengo 1 o 2 elementos en mi prueba) – Myster

+0

Con tan pocos elementos en la lista , el rendimiento alcanzado para configurar los enumeradores "adicionales" para Select/Aggregate parecerá bastante grave en comparación con una solución más imperativa. Al igual que con la mayoría de las soluciones funcionales, la pregunta es si la relación rendimiento/legibilidad es aceptable. Dado lo poco familiar que Aggregate sería para la mayoría de las personas, sería fácil concluir que en este caso la solución imperativa es "mejor" independiente del rendimiento. – dahlbyk

+0

Después de haber escrito en ambos sentidos, estoy de acuerdo. The Aggregate es bastante críptico, pero es una buena herramienta para tener en mi cuadro ;-) – Myster

3

la función de agregado acepta un parámetro delegado. Usted define el comportamiento que desea al cambiar el delegado.

var res = data.Aggregate((current, next) => current + ", " + next.Key + ": " + next.Value); 
+6

Si está agregando en un tipo que no sea la fuente que necesita para especificar una semilla. Especificando "" como una semilla se compilaría, pero el resultado comenzará con ",". – dahlbyk

4

agregado tiene 3 sobrecargas, lo que podría utilizar el que tiene diferentes tipos de acumular los elementos que está enumerando.

Tendría que pasar un valor de inicialización (su clase personalizada) y un método para agregar fusionar la semilla con un valor. Ejemplo:

MyObj[] vals = new [] { new MyObj(1,100), new MyObj(2,200), ... }; 
MySum result = vals.Aggregate<MyObj, MySum>(new MySum(), 
    (sum, val) => 
    { 
     sum.Sum1 += val.V1; 
     sum.Sum2 += val.V2; 
     return sum; 
    } 
Cuestiones relacionadas