У нас есть API для работы с данными, поступающими из разных источников (базы данных, веб-сервисы, простой текст, ...), поэтому мы храним их в структуре списка. У нас есть этот код для выбора некоторых столбцов из них и применения функций для получения новых данных (как сумма двух столбцов, ...)
Func<dynamic[], object>[] leftFunctions = new Func<dynamic[], object>[this.Columns.Count];
IEnumerable<dynamic[]> returnValue = null
j = 0;
foreach (JoinDataColumn dataColum in this.Columns.OrderBy(x => x.Index))
{
//Obtenemos para cada columna la funcion
leftFunctions[j++] = dataColum.getLeftFunction(LeftDataQuery);
}
returnValue = (await LeftDataQuery.ExecuteAsync(parameters))
.Select(x => leftFunctions.Select(f => f.Invoke(x)).ToArray());
В приведенном выше коде: LeftDataquery - это класс для получения списка с данные, выполняющие это и возвращающие List<object[]>
await LeftDataQuery.ExecuteAsync(parameters)
LeftFuncions - это формулы для создания новых данных из исходных данных, "lefdataquery [1] + lefdataquery [2]" или просто "lefdataquery [0]" для получения данные первого столбца.
В классе JoinDataColumn у меня есть описание каждого столбца списка результатов: имя, тип и функция агрегирования.
В конце пользователь Можно выбрать столбцы для группирования и формулу агрегирования для других (сумма, максимум, минимум, количество отличных, ...). Итак, теперь у меня есть возвращаемое значение с подмножеством столбцов исходного источника и списком индексов со столбцами для группировки и списком индексов с их формулой агрегации (например, индекс 1 представляет собой SUM и т. Д.)
public enum DataColumnAggregation { NONE = 0, SUM = 1, MAX = 2, MIN = 3 }
Любая идея о том, как сгруппировать по этим данным и получить SUM / MAX / MIN, ..
Выполняя какой-то тест, я написал этот код, но проблема в том, что Groupby не работает с массивом объектов в качестве параметра. Любая идея, чтобы GroupBy работал с этим подходом? 101
public enum DataColumnAggregation { NONE = 0, SUM = 1, MAX = 2, MIN = 3 }
static void Main(string[] args)
{
List<object[]> returnValue = new List<object[]> { new object[] { "C1", 1, 2 }, new object[] { "C2", 3, 4 }, new object[] { "C1", 1, 3 } };
DataColumnAggregation[] config = new DataColumnAggregation[] { DataColumnAggregation.NONE, DataColumnAggregation.SUM, DataColumnAggregation.MAX };
//TODO agregar por la columna 0 , sumar la columna 1 y maximo de la columna 2 de returnvalue
var resultado2 = returnValue.GroupBy(x => getGroupByColumns(x,config)).Select(x=>agregar(x, config));
}
private static object[] agregar(IGrouping<string[], object[]> x, DataColumnAggregation[] config)
{
List<object> result = new List<object>();
for (int i = 0; i < config.Length; i++)
{
if (config[i] == DataColumnAggregation.NONE)
{
result.Add(x.Select(xy => xy[i]).FirstOrDefault());
}
if (config[i] == DataColumnAggregation.SUM)
{
result.Add(x.Sum(xy => Convert.ToInt32(xy[i])));
}
if (config[i] == DataColumnAggregation.MAX)
{
result.Add(x.Max(xy => xy[i]));
}
if (config[i] == DataColumnAggregation.MIN)
{
result.Add(x.Min(xy => xy[i]));
}
}
return result.ToArray();
}
private static string[] getGroupByColumns(object[] x, DataColumnAggregation[] config)
{
List<string> group = new List<string>();
for (int i = 0; i< config.Length; i++)
{
if (config[i] == DataColumnAggregation.NONE) group.Add(x[i].ToString());
}
return group.ToArray();
}
Спасибо