linq 如何在c#中对DataTable中的任意列执行任意聚合方法?

qjp7pelc  于 2023-01-15  发布在  C#
关注(0)|答案(1)|浏览(231)

这个问题很可怕我知道。如果我能说得更好,我也许能找到解决办法。细节是这样的:
假设我有一个DataTable,它有三列,分别命名为“one”、“two”和“three”,所有列都是int类型。如果我想要第三列的和,这很简单:

var sum = DataTable.AsEnumerable().ToList().Sum(row => row["three"] as int?).Value;

由于我处理的是基础结构级别的内容和行的子集,因此最好将其视为单独类上的方法。

var sum = GetSummary();
...
public class calculator {
    List<DataRow> data;
    public int GetSummary() { return this.data.Sum(row => row["three"] as int?).Value; }
}

困难的部分是我需要允许调用者指定聚合方法和要在其上执行聚合的列。

var desire = <get the average of the column called "two">
var result = GetAggregation(DataTable.AsEnumerable().ToList(), desire);
...
public class calculator {
    List<DataRow> data;
    public int GetAggregation(List<DataRow> data, <something> actionToPerform) { ... }
}

我的desire是什么?它是一个Func()吗?还是完全不同的东西?在这里的例子中它会是什么样子?
我能想到的最好的办法是:

public class calculator {
    List<DataRow> data;
    public T? DoAggregation<T> (string column, Func<IEnumerable<T?>, T> desire) {
        var subset = data.Select(row => row.Field<T>(column)).ToArray();
        return desire(subset);
    }
}

public class tester {
    public class DoTest() {
        var mycalc = new calculator();
        var avgResult = mycalc.DoAggregation<double>("two", desire: (data) => data.Average());
        var sumResult = mycalc.DoAggregation<int>("three", desire: (data) => data.Sum());
    }
}

这是一个进步,但它也有自己的问题。因为我需要存储这些desires,我的计算器需要一个List<Func<IEnumerable<T>, T>>类型的集合......但我不能有不同类型的desires(int与decimal)。我该如何处理像<add column one to column three on each row and take the average across all rows>这样的东西呢?

p4tfgftt

p4tfgftt1#

虽然不太通用,但我找到了一个适合我的解决方案。这个组件用于呈现报表,所以它所做的任何事情都将导致字符串。我的问题的最后一段关注的是返回不同的类型,但这不是一个真正的问题。
话虽如此,我最终得到了:

public void AddDetailComponent(Func<DataRow, string> toPerform) {}

根据@NetMage的评论,这个组件将被其他程序员使用。我必须相信他们有能力编写返回字符串的函数。如果我不能相信,我需要看看谁被雇佣了。
典型用法如下所示:

report.AddDetailComponent((data) =>
{
    var value = (bool)data[DataTableColumns.FirstColumnName] ? (int?)data[DataTableColumns.SecondColumnName] * 2 : (int?)data[DataTableColumns.SecondColumnName] / 2;
            return value.ToString();
});

相关问题