.net 重新排列数据表

dwbf0jvd  于 2023-02-26  发布在  .NET
关注(0)|答案(1)|浏览(126)

我正在将一个excel文件导入到一个数据表(dtImport)中,并将该数据重新排列到另一个数据表(dtImportParsed)中。
下面是我第一次导入数据表(dtImport)时它的样子。

这就是我尝试重新排列数据表的方法(dtImportParsed):

我现在使用嵌套的for循环来完成这个任务,但是这需要很长的时间。例如,一个有36列和4,000行的工作表需要大约30-40分钟才能完成。有没有其他方法可以加快速度呢?
下面是我的代码:

for (int c = 2; c < dtImport.Columns.Count; c++) //for each date column
            {
                for (int r = 1; r < dtImport.Rows.Count; r++)
                {
                    if (dtImportParsed.Rows.Count == 0)
                    {
                        DataRow dataRowImport = dtImportParsed.NewRow();
                        dataRowImport["Date"] = dtImport.Columns[c].ColumnName.ToString().Trim();
                        dataRowImport["account_id"] = dtImport.Rows[r]["account_id"].ToString().Trim();
                        dataRowImport[dtImport.Rows[r]["Event Name"].ToString().Trim()] = dtImport.Rows[r][c].ToString().Trim();
                        dtImportParsed.Rows.Add(dataRowImport);
                    }
                    else
                    {
                        for (int i = 0; i < dtImportParsed.Rows.Count; i++)
                        {
                            if (dtImportParsed.Rows[i]["account_id"].ToString() == dtImport.Rows[r]["account_id"].ToString())
                            {
                                if (dtImportParsed.Rows[i]["Date"].ToString() == dtImport.Columns[c].ColumnName.ToString())
                                {
                                    dtImportParsed.Rows[i][dtImport.Rows[r]["Event Name"].ToString().Trim()] = dtImport.Rows[r][c].ToString().Trim();
                                    break;
                                }
                            }
                            else if (i == dtImportParsed.Rows.Count - 1)
                            {
                                DataRow dataRowImport = dtImportParsed.NewRow();
                                dataRowImport["Date"] = dtImport.Columns[c].ColumnName.ToString().Trim();
                                dataRowImport["account_id"] = dtImport.Rows[r]["account_id"].ToString().Trim();
                                dataRowImport[dtImport.Rows[r]["Event Name"].ToString().Trim()] = dtImport.Rows[r][c].ToString().Trim();
                                dtImportParsed.Rows.Add(dataRowImport);
                            }
                        }
                    }

                }
            }
mkshixfv

mkshixfv1#

用于生成预期结果的算法开销太大!它将按(c x r x i)的顺序执行,其中i > r是因为在最终表中注入了空字段;实际上它是一个O(n3)算法!而且你通过迭代DataRow来在DataTable上执行它,这可能对你的需求来说不是有效的。
如果您的源数据集
不是很大
(如您所提到的),并且您没有内存限制,我建议您使用基于索引的数据结构在内存中安排预期的数据集**。

var arrangeDragon = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();

龙进来了!吃掉了里面的for

for (int c = 2; c < dtImport.Columns.Count; c++) //for each date column
{
    for (int r = 1; r < dtImport.Rows.Count; r++)
    {
        // ...

        // instead of:     for (int i = 0; i < dtImportParsed.Rows.Count; i++) ...
        string date = dtImport.Columns[c].ColumnName.ToString().Trim();
        string accountId = dtImport.Rows[r]["account_id"].ToString();
        string eventName = dtImport.Rows [r]["Event Name"].ToString().Trim();

        if (!arrangeDragon.ContainsKey(date))
            arrangeDragon.Add(date, new Dictionary<string, Dictionary<string, string>>());

        if (!arrangeDragon[date].ContainsKey(accountId))
            arrangeDragon[date][accountId] = new Dictionary<string, string>();

        if (!arrangeDragon[date][accountId].ContainsKey(eventName))
            arrangeDragon[date][accountId][eventName] = dtImport.Rows[r][c].ToString().Trim();

        // ...
    }
}

这些检查将在O(1)而不是O(i)中执行,因此总开销将减少到O(n2),这是迭代表的本质:)
时间复杂度O(1):

string data_field = arrangeDragon["1/1/2022"]["account1"]["Event1"];
Assert.AreEqual(data_field, "42");

现在,您可以迭代嵌套的Dictionary一次并构建dtImportParsed
如果您的数据集很大或者主机内存很低,那么您需要其他解决方案,而这些解决方案不是您所遇到的问题;)
祝你好运

相关问题