c# list如何实现动态分组?

目前我只会对列表的固定的多个字段进行分组,能否实现让用户选择多个字段进行分组?不要使用条件列举所有选择情况,字段数很多,组合出的数量也很大,没有操作性。
代码如下,RuleType, RuleLevel是两个分组字段,如何动态指定其他字段?使用表达式树构造lambda表达式是否可行?如何实现呢?谢谢!

StatisticList = DataList.GroupBy(t => new { t.RuleType, t.RuleLevel})
.Select(g => new Sta{
Type = g.Key.RuleType,
Level = g.Key.RuleLevel,
ScoreTop = g.Sum(t => t.ScoreTop),
}).ToList();

2个回答

帮你写了一个
图片说明

完整代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Q703207
{
    static class LinqExt
    {
        public class DGroupBy<T> : IGrouping<object[], T>
        {
            private List<T> _innerlist = new List<T>();

            private object[] _key;

            public DGroupBy(object[] key) { _key = key; }

            public object[] Key
            {
                get { return _key; }
            }

            public void Add(T value)
            {
                _innerlist.Add(value);
            }

            public IEnumerator<T> GetEnumerator()
            {
                return this._innerlist.GetEnumerator();
            }

            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return this._innerlist.GetEnumerator();
            }
        }

        public static IEnumerable<IGrouping<object[], T>> DynamicGroupBy<T>(this IEnumerable<T> data, string[] keys)
        {
            List<DGroupBy<T>> list = new List<DGroupBy<T>>();
            foreach (var item in data.Select(x => new { 
                k = keys.Select(y => x.GetType().GetProperty(y).GetValue(x, null)).ToArray(),
                v = x
            }))
            {
                DGroupBy<T> existing = list.SingleOrDefault(x => x.Key.Zip(item.k, (a, b) => a.Equals(b)).All(y => y));
                if (existing == null)
                {
                    existing = new DGroupBy<T>(item.k);
                    list.Add(existing);
                }
                existing.Add(item.v);
            }
            return list;
        }
    }

    class User
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public string City { get; set; }
        public override string ToString()
        {
            return string.Format("{0},{1},{2},{3}", ID, Name, Age ,City);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<User> users = new List<User>()
            {
                new User() { ID = 1, Age = 20, City = "BJ", Name = "A" },
                new User() { ID = 2, Age = 20, City = "BJ", Name = "B" },
                new User() { ID = 3, Age = 20, City = "BJ", Name = "C" },
                new User() { ID = 4, Age = 20, City = "SH", Name = "D" },
                new User() { ID = 5, Age = 30, City = "SH", Name = "E" },
                new User() { ID = 6, Age = 30, City = "SH", Name = "F" },
                new User() { ID = 7, Age = 30, City = "CD", Name = "G" },
                new User() { ID = 8, Age = 30, City = "CD", Name = "H" },
                new User() { ID = 9, Age = 30, City = "HK", Name = "I" },
                new User() { ID = 10, Age = 30, City = "HK", Name = "J" },
            };
            var query = users.DynamicGroupBy(new string[] { "City" });
            foreach (var item in query)
            {
                Console.WriteLine("Key: {0}", string.Join(",", item.Key.Select(x => x.ToString())));
                foreach (var item1 in item)
                    Console.WriteLine("\t" + item1);
            }
        }
    }
}

因为csdn的女产品瞎搞,不得已,随便再问两个C#问题采纳我的回答,帮你用表达式树优化下代码(用反射比较慢)。

谢谢caozhy在深夜中的回答。本没期望有人回复,想不到这么快就有写好的代码了,十分感激!我再提2个问题,恳请提供完整代码。

caozhy
贵阳老马马善福专业维修游泳池堵漏防水工程 https://ask.csdn.net/questions/703232
大约一年之前 回复
caozhy
贵阳老马马善福专业维修游泳池堵漏防水工程 已经更新回答。等你写好问题并且采纳好,可以给你再优化下。昨天太晚了,写得比较简单
大约一年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!