【问题标题】:Generating Stats from Datagridview rows从 Datagridview 行生成统计信息
【发布时间】:2012-03-27 05:47:26
【问题描述】:

我正在处理一个项目的一部分,它从 Postgres 数据库服务器解析日志。 该应用程序是在 C sharp Framework 4.0 中开发的。

生成日志并显示在 DataGridView 上,其中包含以下列

resultCode       Statement                  Starttime                   Duration
XT001         select * from PizzaMade    01-02-2012 03:10:14         00:04:10
  • 有许多格式相同的日志。
  • Datagridview 通过解析文本文件从另一个循环中填充。

我的工作是从 Grid 中可用的数据以下列格式生成统计数据

Statement                                 Count        countpercent                    Occurs_on

select * from PizzaMade                     3             1.42        01/02 at 03pm   [00:04:10], 01/02 at 04 [00:01:04]
select id,qty,table from PizzaMade          12             5.12           ...........

所以基本上统计数据反映了以下内容

  • a) 语句已执行
  • b) 计算它在网格中出现的次数
  • c) 计数百分比,基本上是此语句占据的总计数部分
  • d) 包含 starttime,duration 的串联字符串

» 首先使用 for 循环将统计信息生成为 Datatable

foreach(DataGridViewRow dr in LogGrid.Rows)
{
// search in the Datatable if the statement is present
// if it is then add count , add starttime and duration to the column
// if not then add a newrow

}

» 填充数据表后,我使用循环来计算 Totalcount

int totalcount = 0;
foreach (DataRow drin StatTable.Rows)
{
totalcount = totalcount + Convert.ToInt32(dr["count"].ToString());
}

» 计算完计数后,有循环计算百分比

foreach (DataRow dr in StatTable.Rows)
{
    int c = Convert.ToInt32(dr["count"].ToString());
    dr["countpercent"] = (c/totalcount)*100;
}

虽然看起来一切正常,但整个方法运行缓慢,行数过多。

  • 能否请您提出提高性能的方法。

谢谢 阿文德

【问题讨论】:

  • 您可以尝试使用 DataTable 的 Compute 方法获取总计数,但我不知道是否会提高性能
  • 我在 100 万条记录的样本数据上测试了计算方法,似乎 foreach 循环需要 545 毫秒,计算方法需要 1850 毫秒。即 foreach 循环更快

标签: c# .net winforms datagridview datatable


【解决方案1】:

由于您正在解析文本日志,因此它可能会通过不在网格中而是在对象中操作来提高性能。此外,网格可以绑定到已解析日志列表。可能是这样的:

public class LogItem
{
    public string ResultCode { get;set;}
    public string Statement { get;set;}
    public DateTime StartTime { get;set;}
    public TimeSpan Duration { get;set;}
}

然后您的网格可以绑定到包含所有已解析日志项的 BindingList。在拥有列表的同时,您可以以更统一的方式访问数据:

foreach (string statement in logItems.Select(x => x.Statement).Distinct())
{
    int count = logItems.Count(x => x.Statement == statement);
    double percentage = count / logItems.Count(); 
    // any additional data
}

如果您想提高性能和花哨,您可以将所有已解析的日志文件保存到数据库并为必要的数据创建查询。

【讨论】:

  • 我将转发此提示,但目前我只能访问 datagridview 中存在的内容。另一种方法从文本文件更新 Datagridview。我的办公桌上没有该代码。因此这个例子没有给出它。
  • 我可以使用这个类并从 Datagridview 行生成列表,这有帮助吗?因为在填充行之后与速度相关的问题。
  • 您可以随时将网格中的数据解析为类似人类的形式并保持这种形式:)
  • @arvind:当然,您可以尝试看看是否有帮助。虽然双重解析有点尴尬。
  • 双解析系统必须等待,因为这是一个重大的代码更改
【解决方案2】:

我有一些建议,

您可以在使用 linq 的循环过程中使用类似的东西。基本上 linq 使用经过优化的查询,性能非常好。

 DataTable obj = new DataTable();
        obj.Columns.Add("count",typeof(Int32));
        DataRow dr = obj.NewRow();
        dr[0] = "10";
        obj.Rows.Add(dr);

        DataRow dr1 = obj.NewRow();
        dr1[0] = "5";
        obj.Rows.Add(dr1);

        obj.Columns.Add("countpercentage");

        int intCount = (from DataRow drrow in obj.Rows
                        select drrow.Field<int>("count")).Sum();

        (from DataRow drtemp in obj.Rows
         select drtemp).ToList<DataRow>()
         .ForEach(x => x.SetField<string>("countpercentage", ((x.Field<Int32>("count")*100) / intCount).ToString()));

【讨论】:

  • 为什么我们在这里计算平均值..(对不起,我对 linq 的了解有限,)
  • 它在两个地方都对'from'关键字产生错误,>>'System.Data.DataRowCollection'不包含'Cast'的定义
  • 我已经通过添加 System.Linq 命名空间来解决错误。它在行中产生另一个错误 > int intCount = (from DataRow drrow in obj.Rows select drrow.Field("count")).Sum();
  • 我尝试了以下方法, int linqSum = (from DataRow dr in dt.AsEnumerable() select Convert.ToInt32(dr["Test"])).Sum();错误是一样的
  • 好的,我尝试将样本数据从 100 万行减少到 10k 行并且它有效。但是减少行数不是解决方案吗?谢谢
猜你喜欢
  • 2014-10-18
  • 1970-01-01
  • 1970-01-01
  • 2010-12-22
  • 2015-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-08
相关资源
最近更新 更多