В общем, хочу написать метод, который на вход принимает:
DataTable
(заранее неизвестная структура),String[]
, где содержатся колонки по которым нужно сделать группировку, Делитель.
Задача в том, что бы выполнить группировку по полям, которые перечислены в массиве, далее внутри каждой группы сделать объединение строк, через делитель.
Т.е дана такая таблица:
Grp Val1 Val2
1 ; v1 ; d1
1 ; v2 ; d2
1 ; v3 ; d3
2 ; v1 ;d1
2 ; v2; d2
2 ; v3 ; d3
На выходе получится 2 строки:
1 ;v1 | v2 | v3; d1 | d2| d3
2 ;v1 | v2 | v3; d1 | d2| d3
При помощи циклов я представляю, как это сделать. Но можно ли это сделать LINQ запросом?
UPD
Ну и вкратце ответ на вопрос "Почему именно DataTable?"
DataTable берется, как результат парсинга Excel, структура которых заранее неизвестна.
Мой выбор пал на DataTable именно из-за возможности на ходу конструировать таблицу.
Вот решение для List<Dictionary<name, value>>
. Возможно, оно обобщается до решения для DataTable
:
Для начала, нам нужен класс, который сравнивает последовательности объектов поэлементно:
class SequenceComparer : IEqualityComparer<List<object>>
{
public bool Equals(List<object> x, List<object> y) =>
x.Zip(y, (o1, o2) => o1.Equals(o2)).All(v => v);
public int GetHashCode(List<object> list) =>
list.Aggregate(0, (v, obj) => v ^ obj.GetHashCode());
}
Имея такой класс, сравнение тривиально. В качестве ключа мы выбираем нужные значения, и используем только что определённый компаратор.
var data = new[]
{
new Dictionary<string, object>()
{ ["Name"] = "Вася", ["Age"] = 25, ["JobTitle"] = "Программист" },
new Dictionary<string, object>()
{ ["Name"] = "Вася", ["Age"] = 22, ["JobTitle"] = "Программист" },
new Dictionary<string, object>()
{ ["Name"] = "Федя", ["Age"] = 54, ["JobTitle"] = "Директор" },
new Dictionary<string, object>()
{ ["Name"] = "Аделаида", ["Age"] = 20, ["JobTitle"] = "Муза" },
new Dictionary<string, object>()
{ ["Name"] = "Федя", ["Age"] = 2, ["JobTitle"] = "Хомячок" },
};
var columns = new[] { "Name", "JobTitle" };
var groups = data.GroupBy(entity => SelectValues(entity, columns), new SequenceComparer());
Получаем 4 группы.
Вроде сделал, но что-то не так изящно получилось, как хотелось=(
var newDt = dt.Clone();
var columns = new[] { "F1" ,"F2"};
var res = dt.AsEnumerable().GroupBy(x => KeySelector(x, columns), (key, rows) => ResultSelector(rows, columns, newDt, " | "), new SequenceComparer());
static List<object> KeySelector(DataRow row, string[] columns)
{
var listObjcets = new List<object>();
foreach (var column in columns)
{
listObjcets.Add(row[column]);
}
return listObjcets;
}
class SequenceComparer : IEqualityComparer<List<object>>
{
public bool Equals(List<object> x, List<object> y) =>
x.Zip(y, (o1, o2) => o1.Equals(o2)).All(v => v);
public int GetHashCode(List<object> list) =>
list.Aggregate(0, (v, obj) => v ^ obj.GetHashCode());
}
static DataRow ResultSelector(IEnumerable<DataRow> rows, string[] columns, DataTable dt, string separator)
{
var newRow = dt.NewRow();
foreach (DataRow row in rows)
{
for (var index = 0; index < row.ItemArray.Length; index++)
{
var item = row.ItemArray[index];
if (columns.Contains(dt.Columns[index].ColumnName))
{
newRow[index] = item;
}
else
{
newRow[index] += DBNull.Value.Equals(newRow[index]) ? item.ToString() : separator + item;
}
}
}
return newRow;
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Делаю лабораторную работу, задание:
Здравствуйте, подскажите, пожалуйста, использую awesomium с помощью webview
клиент на андроиде передает multipart/form-data данные серверу на c# строковые данные извлекаются без проблем, а вот файлы разобрать не могу android использует...