0

N在 Excel 电子表格上有行(可能不少于 1000 行)。在这张表中,我们的项目有 150 列,如下所示:

在此处输入图像描述

现在,我们的应用程序需要从 GUI 表上的 excel 文件表中复制(使用 normal Ctrl+C)和粘贴(使用)数据。Ctrl+V我通过使用分而治之或其他一些机制来增加。目前我不太确定该怎么做。这是我的代码的一部分:

上面的代码按行调用,如下所示:

请知道我的问题需要比代码优化更多的算法解决方案,但是任何包含代码相关优化的答案也将不胜感激。(标记Linq是因为虽然没有看到我一直在我的代码的某些部分使用 linq)。

4

7 回答 7

6

1. IIRCdRow["Condition"]dRow[index]每次都要查找要慢得多。在调用之前找出列有哪些索引。

public virtual void ValidateAndFormatOnCopyPaste(DataTable DtCopied, int CurRow, int conditionIndex, int valueIndex)
{
    foreach (DataRow dRow in dtValidateAndFormatConditions.Rows)
    {
         string Condition = dRow[conditionIndex];
         string FormatValue = Value = dRow[valueIndex];
         GetValidatedFormattedData(DtCopied,ref Condition, ref FormatValue ,iRowIndex);
         Condition = Parse(Condition);
         dRow[conditionIndex] = Condition;
         FormatValue = Parse(FormatValue );
         dRow[valueIndex] = FormatValue;
    }
}

2.如果您正在实时更新 excel 文档,您还应该在此过程中锁定工作表更新,因此不会在每次单元格更改时重新绘制文档。

3. virtual方法也有性能损失。

于 2013-11-14T08:45:55.187 回答
2

对此类问题的一般答案是,您希望尽可能多地将较重的处理移出行循环,因此它只需要执行一次,而不是对每一行执行一次。

如果不确切知道您的验证/格式化系统是如何工作的,很难提供更多细节,但我可以提供一些“指针”:

  • 是否可以从您的这个条件表中构建某种缓存数据结构?这将从您的内部循环中消除所有繁重的 DataTable 操作
  • 我能想到的大规模验证/格式化的最有效解决方案是根据您的一组条件构建一个 C# 脚本,将其编译成一个委托,然后对每一行进行评估。我不知道这是否可能解决您的问题...
于 2013-11-18T14:39:05.773 回答
1

该算法有两个改进建议:-

如果可能的话,aU 可以使用多线程以通过常数因子来加速过程(需要测试以获得实际值)。您可以使用多线程并行评估行。

湾。如果即使一列无效也可以停止处理行,那么您可以停止处理该行。此外,您可以分析大量数据的输入数据,并以递减无效的概率排列列,然后按此计算顺序检查列。此外,您还可以按照您对检查验证的列所做的方式安排验证条件的谓词

可能会提高性能的建议算法:-

for i in totalconds :
   probability(i) = 0

for record in largeDataSet : 
    for col in record : 
        for cond in conditions :
            if invalid(cond,col) : 
               probability(cond)++

sort(probability(cond),condorder,order=decreasing)

按 condorder 顺序检查条件

这是一种学习算法,可用于计算谓词的评估顺序,以对条件进行有效的短路评估,但有效输入需要相同的时间。您可以在大型样本输入数据集上离线评估此订单,并在实时使用期间存储在数组中。

编辑:我错过的另一个改进是对具有小范围有效值的列使用哈希表,因此我们不评估该列的条件,而是检查它是否在哈希表中。同样,如果无效值范围很小,那么我们在哈希表中检查它们。哈希表可以在使用文件开始评估之前填充。

于 2013-11-12T09:49:45.300 回答
0

您可以使用数据表。试试这个 datatable.Select(string.Format("[Col1] = '{0}'", id)).ToList().ForEach(r => r["Col1"] = Data); 查看链接 https://msinternal1.engageexpress.com/sf/MTY1NDNfMTY4NTM4

于 2013-11-14T09:24:04.640 回答
0

前置步骤:

  • 创建一个接受 1 个数据行并对其进行处理的任务类
  • 创建任务队列
  • 使用 Y 个 worker 创建一个线程池

算法

  1. 当您获得 N 行时,将它们作为任务添加到您的任务队列中
  2. 让工作人员开始从任务队列中获取任务
  3. 随着任务响应返回,更新您的数据表(可能最初是一个克隆)
  4. 完成所有任务后,返回您的新数据表

可能的改进

  • 正如维克拉姆所说,你可能会短路你的条件,如果值为 10,你知道它已经是一个错误,不要费心检查其余的 140 个条件,但那只有在符合你的要求的情况下,如果你的要求需要对所有 150 个进行检查的条件,那么您将无法逃脱该条件
  • 更改任务类以接收行数据列表而不是 1,如果线程之间的上下文切换很快完成,这可能会有所改善

我还没有真正考虑过的其他想法

  • 首先对数据进行排序,也许通过短路某些已知条件可以提高速度
  • 对整行进行校验和,将其存储到数据库中,基本上缓存参数/结果,以便下次运行具有完全相同的值/字段的东西时,您可以将其从缓存中拉出
  • 整行的另一个校验和为您购买的是更改,假设您有某种键并且您正在寻找更改的数据,除键之外的所有内容的校验和会告诉您某些值是否更改以及它是否值得查看所有其他列的条件
于 2013-11-13T08:16:16.313 回答
0

我知道这是一种蛮力,但你可以将它与其他人的建议结合起来:

Parallel.ForEach(dtValidateAndFormatConditions.Rows, dRow =>
        {
             string Condition = dRow[conditionIndex];
             string FormatValue = Value = dRow[valueIndex];
             GetValidatedFormattedData(DtCopied,ref Condition, ref FormatValue ,iRowIndex);
             Condition = Parse(Condition);
             FormatValue = Parse(FormatValue);
             lock (dRow)
             {
                 dRow[conditionIndex] = Condition;
                 dRow[valueIndex] = FormatValue;
             }
        });
于 2013-11-15T14:21:43.623 回答
0

'string Condition = dRow["Condition"]' 之类的操作相当繁重,因此我建议将行枚举(for-cycle)从 ValidateAndFormat 方法移动到 ValidateAndFormatOnCopyPaste 方法,立即调用 GetValidatedFormattedData。

于 2013-11-10T04:20:47.530 回答