繁体   English   中英

Select 列动态来自数据表 C#

[英]Select columns dynamically from Datatable C#

我有一个如下所示的Datatable

第 1 列 第 2 列 第 3 列 第 4 栏
11 10 20 3
35 45 5 10
11 10 30 5
30 13 15 1

数据表有大约 30 列。 示例我提到了 4 列(如上)

var groupbyColumns=list<string>(){"column1","column2"};

var aggregateColumns=List<string>(){"Column3"};

注意:列将根据用户从 UI 中的选择动态更改。

预期结果:

第 1 列 第 2 列 第 3 列
11 10 50
35 45 5
30 13 15

我必须根据groupbyColumns列表进行分组,然后根据aggregateColumn列表对列进行求和。

例如,如果groupbyColumns包含 2 列并且aggregateColumn包含 2 列意味着结果必须是 4 列。

有人请帮我实现这一目标吗?

使用IEqualityComparer for IEnumerable提供序列相等性,您可以生成可用于GroupBy的密钥。 我使用 static 方法来简化它的创建过程。

public static class Make {
    public static IEqualityComparer<IEnumerable<T>> IESequenceEqual<T>() => new IEnumerableSequenceEqualityComparer<T>();
    public static IEqualityComparer<IEnumerable<T>> IESequenceEqual<T>(T _) => new IEnumerableSequenceEqualityComparer<T>();

    private class IEnumerableSequenceEqualityComparer<T> : IEqualityComparer<IEnumerable<T>> {
        public bool Equals(IEnumerable<T> x, IEnumerable<T> y) =>
            Object.ReferenceEquals(x, y) || (x != null && y != null && (x.SequenceEqual(y)));

        public int GetHashCode(IEnumerable<T> items) {
            // Will not throw an OverflowException
            //unchecked {
            //    return items.Where(e => e != null).Select(e => e.GetHashCode()).Aggregate(17, (a, b) => 23 * a + b);
            //}
            var hc = new HashCode();
            foreach (var item in items)
                hc.Add(item);
            return hc.ToHashCode();
        }
    }
}

由于您似乎指定答案应该是DataTable ,因此您需要一个扩展方法来将结果转换为一个。 我使用IDictionary<string,object>作为中介在动态生成时传递列名和值。

public static class IEnumerableExt {
    public static DataTable ToDataTable(this IEnumerable<IDictionary<string, object>> rows) {
        var dt = new DataTable();
        if (rows.Any()) {
            foreach (var kv in rows.First().OrderBy(e => e.Key))
                dt.Columns.Add(kv.Key, kv.Value.GetType());

            foreach (var r in rows)
                dt.Rows.Add(r.Values.Select(v => (object)v).ToArray());
        }
        return dt;
    }
}

现在您只需按groupByColumns ,汇总您的aggregateColumns并将结果转换为DataTable 我使用ValueTuple来表示要转换为Dictionary的每个列名、值对。

var groupByColumns = new[] { "Column1", "Column2" }.ToList();
var aggregateColumns = new[] { "Column3" }.ToList();

var ans = src.AsEnumerable()
             .GroupBy(r => groupByColumns.Select(c => r[c]), Make.IESequenceEqual<object>())
             .Select(rg => groupByColumns.Zip(rg.Key, (c,v) => (c, v))
                                         .Concat(aggregateColumns.Select(c => (c, v:(object)rg.Sum(r => Convert.ToDouble(r[c])))))
                                         .ToDictionary(ck => ck.c, ck => ck.v))
             .ToDataTable();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM