Linq Aggregate tipi complessi in una stringa
-
19-09-2019 - |
Domanda
Ho visto il semplice esempio della funzione di aggregazione .net lavorare in questo modo:
string[] words = { "one", "two", "three" };
var res = words.Aggregate((current, next) => current + ", " + next);
Console.WriteLine(res);
Come potrebbe la funzione 'aggregata' essere utilizzata se si vuole aggregare i tipi più complessi? Per esempio: una classe con 2 immobili come 'chiave' e 'valore' e si desidera che l'output come questo:
"MyAge: 33, MyHeight: 1.75, MyWeight:90"
Soluzione
Sono disponibili due opzioni:
-
Progetto per un
string
e poi aggregata: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);
Questo ha il vantaggio di utilizzare il primo elemento
string
come il seme (senza anteporre ""), ma si consumano più memoria per le stringhe create nel processo. -
Utilizzare un sovraccarico di aggregazione che accetta un seme, forse 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);
Il secondo delegato converte la nostra
StringBuilder
in unstring,
utilizzando il condizionale per tagliare l'inizio "".
Altri suggerimenti
aggregato ha 3 sovraccarichi, così da poter utilizzare quello che ha diverso tipo di accumulare gli articoli che state enumerazione.
Si avrebbe bisogno di passare a un valore di semi (la classe personalizzata), e un metodo per aggiungere unire il seme con un valore. Esempio:
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;
}
la funzione di aggregazione accetta un parametro delegato. Si definisce il comportamento che volete modificando il delegato.
var res = data.Aggregate((current, next) => current + ", " + next.Key + ": " + next.Value);
In alternativa, utilizzare 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);