Reputation: 323
If there is a DataTable called STUDENTS
SubjectID StudentName
---------- -------------
1 Mary
1 John
1 Sam
2 Alaina
2 Edward
How can we get the below DataTable as a result using Linq:
SubjectID StudentName
---------- -------------
1 Mary, John, Sam
2 Alaina, Edward
I tried achieving this result using the foreach loop crawling through each datarow one by one but came across major performance hit.
Not good with Linq but trying my hands on it. I would post my answer once I get something concrete but any help would be appreciated in between.
Sample working code without using Linq but not giving the desired performance. The below foreach loop is taking around 15mins if the DataTable dt2 has around 3500 records.
DataTable dtFiles = dt2.Clone();
//Logic to filter out the files by keyword name filter.
foreach (DataRow row in dt2.Rows)
{
string studentid = row.Field<string>("StudentID");
string filter = "StudentID = '" + studentid + "'";
if(dtFiles.Select(filter).Count() == 0)//this means keyword is new
{
DataRow dr = dtFiles.NewRow();
dr["StudentName"] = row["StudentName"];
dr["StudentID"] = row["StudentID"];
dtFiles.Rows.Add(dr);
}
else
{
dtFiles.Select(filter).First<DataRow>()["StudentName"] += "," + row.Field<string>("StudentName");//Rows[0]
}
}
Upvotes: 1
Views: 1155
Reputation: 429
Here is a little bit of a variation of the previous solution:
DataTable dt = dtFiles.Clone();
(from r in dtFiles.AsEnumerable()
group r by r.Field<int>("SubjectID") into g
select g)
.Aggregate(dt, (d, g) =>
{
dt.Rows.Add(g.Key, String.Join(", ", g.Select(r => r.Field<string>("StudentName"))));
return dt;
});
Your result will be in the cloned DataTable dt.
Upvotes: 1
Reputation: 236188
Get grouped data
var subjects =
from r in dtFiles.AsEnumerable()
group r by r.Field<int>("SubjectID") into g
select new {
ID = g.Key,
Students = String.Join(", ", g.Select(r => r.Field<string>("StudentName"))
};
Then build DataTable (if you need it)
DataTable dt = new DataTable();
dt.Columns.Add("SubjectID", typeof(int));
dt.Columns.Add("StudentName", typeof(string));
// or you can just clone existing DataTable:
DataTable dt = dtFiles.Clone();
foreach(var subject in subjects)
dt.Add(subject.ID, subject.Students);
Upvotes: 4