Linq Совокупность сложных типов в строку
Я видел простой пример функции .net Aggregate:
string[] words = { "one", "two", "three" };
var res = words.Aggregate((current, next) => current + ", " + next);
Console.WriteLine(res);
Как можно использовать функцию "Агрегат", если вы хотите объединить более сложные типы?
Например: класс с двумя свойствами, такими как "ключ" и "значение", и вы хотите, чтобы этот вывод выглядел следующим образом:
"MyAge: 33, MyHeight: 1.75, MyWeight:90"
Ответы
Ответ 1
У вас есть два варианта:
-
Спроектировать в string
, а затем скомпилировать:
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);
Преимущество состоит в том, что первый элемент string
используется как семя (без добавок), но будет потреблять больше памяти для строк, созданных в процессе.
-
Используйте агрегатную перегрузку, которая принимает семя, возможно, 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);
Второй делегат преобразует наш StringBuilder
в string,
, используя условное выражение для обрезания начального ",".
Ответ 2
Агрегат имеет 3 перегрузки, поэтому вы можете использовать тот, который имеет другой тип, чтобы накапливать элементы, которые вы перечисляете.
Вам нужно будет передать начальное значение (ваш собственный класс) и метод для добавления слияния семени с одним значением. Пример:
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;
}
Ответ 3
Функция Aggregate принимает параметр делегата. Вы определяете поведение, которое вы хотите, изменяя делегат.
var res = data.Aggregate((current, next) => current + ", " + next.Key + ": " + next.Value);