LINQ - 在运行时确定多列并对 DataTable 进行分组

3
使用.NET 3.5时,我需要按多个列对DataTable进行分组,其中列名包含在IEnumerable中。
// column source
IEnumerable<string> columns;
DataTable table;

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

通常情况下,???会是一个匿名类型,正如这里所描述的一样,但我需要使用columns作为列来源。这是否可行?
1个回答

2
最简单的方法是创建一个函数,选择所需的列并创建哈希用于比较。我会这样做:
Func<DataRow, IEnumerable<string>, string> f = (row, cols) => 
    String.Join("|", cols.Select(col => row[col]));

这是一个函数,它接受一个 DataRow 和一个 IEnumerable<string>。它将IEnumerable<string>(列名)映射为相应的列值(cols.Select(col => row[col]))),然后使用|字符连接这些值。我选择了这个字符,因为它不太可能被包含在您的字段中,但您可能想要换成另一个分隔符。

然后就简单了。

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

理想情况下,我们应该选择更好的类型而不是用任意分隔符连接的字符串。但我预计选择一个对象会因为引用类型的比较而导致问题,即使两个对象拥有相同的属性,它们也不相等。

我不得不在投影中添加一个强制转换才能使其工作:Func<DataRow, IEnumerable<string>, string> f = (row, cols) => String.Join("|", cols.Select(col => (string)row[col]).ToArray()); - 但我想知道你能否解释一下这行代码实际上是如何工作的?.GroupBy(row => f(row, columns)) - 这个函数返回一个字符串,但如果你用一个字符串替换它,它就不能工作了!分组如何知道在构造函数中生成字符串后查看列值?如果您能指出任何解释这个问题的资源,我会很高兴。 - Joanna Derks
1
@Joanna 很高兴能帮到你。它能正常工作的原因是函数返回的字符串不仅仅是“任意字符串”,而是包含列值的字符串。如果任何两行的列值匹配,则字符串将匹配,并且它们将被“分组”。 - Kirk Broadhurst
所以它执行(row => f(row, columns)),最终得到像row => 1|10row => 2|987这样的值,并将它们作为分组的键,因此如果其中任何一个重复出现,则会与前一个出现一起分组。好的,这很有道理。谢谢! - Joanna Derks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接