【问题标题】:Join rows using C# Linq使用 C# Linq 连接行
【发布时间】:2014-05-30 05:40:24
【问题描述】:

如果有一个名为 STUDENTS 的 DataTable

SubjectID       StudentName
----------      -------------
1               Mary
1               John
1               Sam
2               Alaina
2               Edward

我们如何使用 Linq 获得以下 DataTable 的结果:

SubjectID       StudentName
----------      -------------
1               Mary, John, Sam
2               Alaina, Edward

我尝试使用 foreach 循环逐个爬取每个数据行来实现此结果,但遇到了严重的性能损失。

Linq 不太好,但我尝试了一下。一旦我得到一些具体的东西,我会发布我的答案,但在这之间的任何帮助将不胜感激。

不使用 Linq 但未提供所需性能的示例工作代码。如果 DataTable dt2 有大约 3500 条记录,则下面的 foreach 循环大约需要 15 分钟。

        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]
            }
        }

【问题讨论】:

  • 我看不出 Linq 会比单次通过集合更快。您在这里谈论多少记录?你想做什么?
  • 数据表有大约 3500 条记录,大约需要 10 - 15 分钟才能完成。我会尽快发布示例代码。
  • 您希望结果为DataTable 的任何特殊原因?您可以轻松地将其作为自定义类型的列表...请注意,如果您首先将所有数据提取到 DataTable 中,则 not 使用 LINQ-to-SQL。
  • 3500 条记录应该只需要几秒钟的时间来处理——有些不对劲:|我相信问题在于使用dtFiles.Select.. - 是否会将循环变为 O(n^2) 或更糟? - 而不是基于哈希的查找/探测。 (我不知道 DataTables 对索引有什么支持。)
  • @Jon Skeet:这里的重点是我正在使用 OledbReader 从 DataTable 中的 excel 中获取数据。现在我希望这些数据采用上面指定的特定格式。

标签: c# .net linq linq-to-sql datatable


【解决方案1】:

获取分组数据

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"))
    };

然后构建DataTable(如果需要)

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);  

【讨论】:

  • 非常感谢,谢尔盖!!它完成了工作!
  • @AnubhavSharma 我希望你的性能有显着提升:)
  • 现在非常快。性能提高了很多倍:)
【解决方案2】:

这里是先前解决方案的一些变体:

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;
         });

您的结果将在克隆的 DataTable dt 中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-12
    • 2020-01-24
    • 1970-01-01
    • 2018-02-20
    相关资源
    最近更新 更多