【问题标题】:LINQ - Group DataTable by multiple columns determined at runtimeLINQ - 按运行时确定的多列对 DataTable 进行分组
【发布时间】:2012-05-10 15:02:39
【问题描述】:

使用 .NET 3.5,我需要将 DataTable 按多列分组,其中列名包含在 IEnumerable 中。

// column source
IEnumerable<string> columns;
DataTable table;

IEnumerable<IGrouping<object, DataRow>> groupings = table
    .AsEnumerable()
    .GroupBy(row => ???);

通常??? 将是here 所述的匿名类型,但我需要使用columns 作为列源。这可能吗?

【问题讨论】:

    标签: linq .net-3.5 datatable group-by


    【解决方案1】:

    最简单的方法是创建一个函数来选择所需的列并创建一个散列以进行比较。我会做这样的事情:

    Func<DataRow, IEnumerable<string>, string> f = (row, cols) => 
        String.Join("|", cols.Select(col => row[col]));
    

    这是一个采用DataRowIEnumerable&lt;string&gt; 的函数。它将IEnumerable&lt;string&gt;(列名)投影到相应的列值(cols.Select(col =&gt; row[col])))中,然后用| 字符连接这些值。我选择这个字符是因为它不太可能包含在您的字段中,但您可能希望换成另一个分隔符。

    那么简单

    IEnumerable<IGrouping<object, DataRow>> groupings = table
        .AsEnumerable()
        .GroupBy(row => f(row, columns));
    

    理想情况下,我们会选择更好的类型——而不是用任意分隔符捆绑在一起的字符串。但是我希望选择一个对象会由于引用类型的比较而导致问题,因为即使它们具有相同的属性,两个对象也不相等。

    【讨论】:

    • 我必须在投影中添加一个演员才能使其工作:Func&lt;DataRow, IEnumerable&lt;string&gt;, string&gt; f = (row, cols) =&gt; String.Join("|", cols.Select(col =&gt; (string)row[col]).ToArray()); - 但我想知道你能否解释一下这条线实际上是如何工作的? .GroupBy(row =&gt; f(row, columns)) - 该函数返回一个字符串,但如果您将其替换为字符串,它将无法工作!一旦在 func 中构造了字符串,分组如何知道查看列值?如果您能指出任何解释这一点的资源,我会很高兴。
    • @Joanna 很高兴它有帮助。它起作用的原因是函数返回的字符串不仅仅是“任何字符串”,它是一个包含列值的字符串。如果任何两行的列值匹配,则字符串将匹配,并且它们将被“分组”。
    • 所以它在做(row =&gt; f(row, columns)),以row =&gt; 1|10row =&gt; 2|987之类的值结束,这些成为分组的键,因此如果其中任何一个重复,它将与前一个分组发生。好的,这很有意义。谢谢!
    猜你喜欢
    • 2014-10-31
    • 1970-01-01
    • 1970-01-01
    • 2017-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-06
    • 2012-09-10
    相关资源
    最近更新 更多