Pergunta

Eu vi o exemplo simples da função .net Aggregate trabalhando assim:

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

Como é que a função 'agregado' ser usado se você deseja agregar tipos mais complexos? Por exemplo: uma classe com 2 propriedades como 'chave' e 'valor' e você quer a saída como esta:

"MyAge: 33, MyHeight: 1.75, MyWeight:90"
Foi útil?

Solução

Você tem duas opções:

  1. Project para um string e depois agregado:

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

    Isto tem a vantagem de usar o primeiro elemento string como a semente (sem prefixado ""), mas irá consumir mais memória para as cordas criadas no processo.

  2. Use uma sobrecarga agregado que aceita uma semente, talvez um 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);
    

    O segundo delegado converte nosso StringBuilder em um string, utilizando o condicional para aparar a partida "".

Outras dicas

Aggregate tem 3 sobrecargas, para que você possa usar o que tem tipo diferente de acumular os itens que você está enumerando.

Você precisaria passar em um valor de semente (sua classe personalizada), e um método para adicionar fundir a semente com um valor. Exemplo:

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

A função Aggregate aceita um parâmetro delegado. Você define o comportamento desejado mudando o delegado.

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

Ou uso String.Join ():

var values = new[] {
    new { Key = "MyAge", Value = 33.0 },
    new { Key = "MyHeight", Value = 1.75 },
    new { Key = "MyWeight", Value = 90.0 }
};
var res = string.Join(", ", values.Select(item => $"{item.Key}: {item.Value}"));
Console.WriteLine(res);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top