【问题标题】:How to select min and max values of a column in a datatable?如何选择数据表中列的最小值和最大值?
【发布时间】:2011-01-27 09:41:25
【问题描述】:

对于以下数据表列,获取最小值和最大值的最快方法是什么?

AccountLevel  
0  
1  
2  
3 

【问题讨论】:

    标签: c# .net select datatable


    【解决方案1】:

    数据表的简单方法可能是:

    int minLavel = Convert.ToInt32(dt.Compute("min([AccountLevel])", string.Empty));
    

    【讨论】:

    • 这是最好的方法,但是你错过了在上面的代码中使用[]的一件事。例如int minLavel = Convert.ToInt32(dt.Compute("min([AccountLevel])", string.Empty));没有方括号它给了我一个错误。
    • 我对此不是很有经验,但是在我开始使用“计算”​​而不是循环等之后,我的程序变得更快了。您只需要确保您的数据格式正确即可使用计算。
    【解决方案2】:
    int minAccountLevel = int.MaxValue;
    int maxAccountLevel = int.MinValue;
    foreach (DataRow dr in table.Rows)
    {
        int accountLevel = dr.Field<int>("AccountLevel");
        minAccountLevel = Math.Min(minAccountLevel, accountLevel);
        maxAccountLevel = Math.Max(maxAccountLevel, accountLevel);
    }
    

    是的,这确实是最快的方法。使用 Linq MinMax 扩展总是会变慢,因为你必须迭代两次。您可能会使用 Linq Aggregate,但语法不会比现在更漂亮。

    【讨论】:

    • 是的,这就是 SLaks 的建议,使用 for 循环作为最快的方式。
    • 是的,但我认为应该是 { int accountLevel = dr.Field("AccountLevel"); min = Math.Min(min, accountLevel); max = Math.Max(max, accountLevel); } 不是吗?
    • @Ahmed:对不起,变量赋值中的错字。固定。
    • 我可能迟到了一点,但 minAccountLevel 不会总是等于 int.MinValue 因为 accountLevel 永远不会小于 int.MinValue 吗? maxAccountLevel 和 int.MaxValue 也是如此,不是吗?
    • @Welton 是的,我搞砸了并调换了前两行。 “min”应该初始化为Int32.MaxValue,“max”应该初始化为Int32.MinValue,这样第一行(如果有的话)总是会更新这些。
    【解决方案3】:

    使用 LINQ。只要将行集合转换为 IEnumerable,它就可以在数据表上正常工作。

    List<int> levels = AccountTable.AsEnumerable().Select(al => al.Field<int>("AccountLevel")).Distinct().ToList();
    int min = levels.Min();
    int max = levels.Max();
    

    已编辑以修复语法;在 DataTables 上使用 LINQ 很棘手,而且聚合函数也很有趣。

    是的,可以通过一个查询完成,但您需要生成一个结果列表,然后在单独的语句中使用 .Min() 和 .Max() 作为聚合函数。

    【讨论】:

    • 但是需要两次迭代。
    • 不知何故,我认为Distinct 不会加快速度——它必须对每个元素进行哈希处理,而MinMax 只是进行比较。
    【解决方案4】:

    这对我来说很好用

    int  max = Convert.ToInt32(datatable_name.AsEnumerable()
                            .Max(row => row["column_Name"]));
    

    【讨论】:

      【解决方案5】:

      最有效的方法(信不信由你)是创建两个变量并编写一个for 循环。

      【讨论】:

        【解决方案6】:
        var answer = accountTable.Aggregate(new { Min = int.MinValue, Max = int.MaxValue }, 
                                                (a, b) => new { Min = Math.Min(a.Min, b.Field<int>("AccountLevel")),
                                                                Max = Math.Max(a.Max, b.Field<int>("AccountLevel")) });
        int min = answer.Min;
        int max = answer.Max;
        

        1 次迭代,linq 风格 :)

        【讨论】:

        • 还没有尝试过,但看起来很有希望 - 您是否将其与直接 for 循环的性能进行了比较?
        • accountTable 是什么类型?对我来说,DataTable 对象似乎不支持Aggregate...
        【解决方案7】:

        另一种方法是

        int minLavel = Convert.ToInt32(dt.Select("AccountLevel=min(AccountLevel)")[0][0]);
        

        我不确定性能部分,但这确实给出了正确的输出

        【讨论】:

        • 我在包含 125k 行的 DataTable 上对此进行了测试。它非常慢。
        【解决方案8】:
        var min = dt.AsEnumerable().Min(row => row["AccountLevel"]);
        var max = dt.AsEnumerable().Max(row => row["AccountLevel"]);
        

        【讨论】:

        • 请对您的答案添加评论,仅代码不清楚。
        【解决方案9】:
        Session["MinDate"] = dtRecord.Compute("Min(AccountLevel)", string.Empty);
        Session["MaxDate"] = dtRecord.Compute("Max(AccountLevel)", string.Empty);
        

        【讨论】:

        • 也许您可以详细说明为什么这是最快的方法?任何论点都可能有助于其他人采纳或跳过您的建议,转而支持其他帖子。
        【解决方案10】:

        在性能方面,这应该是可比的。使用 Select 语句和 Sort 获取列表,然后选择第一个或最后一个(取决于您的排序顺序)。

        var col = dt.Select("AccountLevel", "AccountLevel ASC");
        
        var min = col.First();
        var max = col.Last();
        

        【讨论】:

          【解决方案11】:

          我不知道我的解决方案如何将性能方面与之前的答案进行比较。

          我知道最初的问题是:在 DataTable 对象中获取最小值和最大值的最快方法是什么,这可能是一种方法:

          DataView view = table.DefaultView;
          view.Sort = "AccountLevel";
          DataTable sortedTable = view.ToTable();
          int min = sortedTable.Rows[0].Field<int>("AccountLevel");
          int max = sortedTable.Rows[sortedTable.Rows.Count-1].Field<int>("AccountLevel");
          

          这是一种无需循环即可实现相同结果的简单方法。但是需要将性能与以前的答案进行比较。以为我最喜欢 Cylon Cats 的回答。

          【讨论】:

            猜你喜欢
            • 2013-05-09
            • 1970-01-01
            • 2021-09-09
            • 2017-05-17
            • 2020-05-16
            • 2021-08-14
            • 2021-05-25
            • 2013-04-03
            • 2019-02-09
            相关资源
            最近更新 更多