Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 按运行时已知的多个键分组_C#_.net_Linq - Fatal编程技术网

C# 按运行时已知的多个键分组

C# 按运行时已知的多个键分组,c#,.net,linq,C#,.net,Linq,我有一个telerik网格,我将对象列表数据绑定到页面上。用户可以在查看数据时根据自己的喜好对列进行分组。我正在编写一个函数,将这些数据导出到excel文档中,并希望保留用户在页面上的分组。我能够获得用户分组所依据的对象属性的字符串名称 我一直关注的是如何在运行时进行分组。有很多这样的例子:当您提前知道时,描述如何在编译时按多个属性分组。然而,直到运行时,我才知道分组依据什么 对于如何在运行时进行分组,有什么建议吗 您可能正在寻找类似以下问题的答案: var myData = gridData.

我有一个telerik网格,我将对象列表数据绑定到页面上。用户可以在查看数据时根据自己的喜好对列进行分组。我正在编写一个函数,将这些数据导出到excel文档中,并希望保留用户在页面上的分组。我能够获得用户分组所依据的对象属性的字符串名称

我一直关注的是如何在运行时进行分组。有很多这样的例子:当您提前知道时,描述如何在编译时按多个属性分组。然而,直到运行时,我才知道分组依据什么


对于如何在运行时进行分组,有什么建议吗

您可能正在寻找类似以下问题的答案:

var myData = gridData.AsEnumerable()
                     .GroupBy(r => r, new MyDataComparer(keys))
                     .ToList();

internal class MyDataComparer : IEqualityComparer<MyDataType>
{
    private readonly string[] _keys;

    public MyDataComparer(string[] keys)
    {
        _keys = keys; // keep the keys to compare by.
    }

    public bool Equals(MyDataType x, MyDataType y)
    {
        // a simple implementation that checks if all the required fields 
        // match. This might need more work.
        bool areEqual = true;
        foreach (var key in _keys)
        {
            areEqual &= (x[key].Equals(y[key]));
        }
        return areEqual;
    }

    public int GetHashCode(DataRow obj)
    {
        // Add implementation here to create an aggregate hashcode.
    }
}    
var myData=gridData.AsEnumerable()
.GroupBy(r=>r,新的MyDataComparer(键))
.ToList();
内部类MyDataComparer:IEqualityComparer
{
私有只读字符串[]\u密钥;
公共MyDataComparer(字符串[]键)
{
_keys=keys;//保留要比较的键。
}
公共布尔等于(MyDataType x,MyDataType y)
{
//一个简单的实现,它检查所有必需的字段
//匹配。这可能需要更多的工作。
布尔等于真;
foreach(变量键输入_键)
{
areEqual&=(x[key].Equals(y[key]);
}
回报是平等的;
}
public int GetHashCode(DataRow obj)
{
//在此处添加实现以创建聚合哈希代码。
}
}    

我会用动态Linq()来实现这一点

例如:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic; //have to install this via nuget or download it

public class Person {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DOB { get; set; }
}


class Program {
    static void Main(string[] args) {
        var peeps = new List<Person>{
            new Person(){ FirstName="Tim", LastName="Smith", DOB = DateTime.Now},
            new Person(){ FirstName="Tim", LastName="Smith", DOB = DateTime.Now.AddDays(1)},
            new Person(){ FirstName="Mike", LastName="Smith", DOB = DateTime.Now.AddDays(2)},
            new Person(){ FirstName="Frank", LastName="Jones", DOB = DateTime.Now.AddDays(3)},
        };

        var eq = peeps.GroupBy("new (LastName, FirstName)", "it").Select("new(it.Key as Key, it as People)"); ;
        foreach (dynamic el in eq) {
            Console.WriteLine(el.Key);
            foreach (var person in el.People as IEnumerable<Person>) {
                Console.WriteLine(person.LastName + " " + person.DOB);
            }
        }            
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Linq.Dynamic//必须通过nuget安装或下载它
公共阶层人士{
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共日期时间DOB{get;set;}
}
班级计划{
静态void Main(字符串[]参数){
var peeps=新列表{
newperson(){FirstName=“Tim”,LastName=“Smith”,DOB=DateTime.Now},
newperson(){FirstName=“Tim”,LastName=“Smith”,DOB=DateTime.Now.AddDays(1)},
newperson(){FirstName=“Mike”,LastName=“Smith”,DOB=DateTime.Now.AddDays(2)},
newperson(){FirstName=“Frank”,LastName=“Jones”,DOB=DateTime.Now.AddDays(3)},
};
var eq=peeps.GroupBy(“new(LastName,FirstName)”,“it”)。选择(“new(it.Key作为Key,it作为人)”;
foreach(均衡器中的动态el){
控制台写入线(el.键);
foreach(将el.People中的person变量设置为IEnumerable){
Console.WriteLine(person.LastName+“”+person.DOB);
}
}            
}
}

您试图根据运行时拥有的特定属性的名称进行分组。 它与此类似,只是它固定在两个过滤器上。这只是你的另一个选择。 使用linq pad进行测试

过滤器的数量是固定的还是动态的

void Main()
{
    var mySchool = new List<School>{
    new School{Student = "Student A", Teacher = "Teacher A", Subject = "Math", Grades = 80},
    new School{Student = "Student B", Teacher = "Teacher A", Subject = "Math", Grades = 65},
    new School{Student = "Student C", Teacher = "Teacher A", Subject = "Math", Grades = 95},
    new School{Student = "Student A", Teacher = "Teacher B", Subject = "History", Grades = 80},
    new School{Student = "Student B", Teacher = "Teacher B", Subject = "History", Grades = 100},
    new School{Student = "Student A", Teacher = "Teacher C", Subject = "English", Grades = 100},
    new School{Student = "Student C", Teacher = "Teacher B", Subject = "English", Grades = 100},
    new School{Student = "Student D", Teacher = "Teacher B", Subject = "English", Grades = 90},
    };


    GroupByFilters("Teacher", "Subject", mySchool);
    GroupByFilters("Subject", "Teacher", mySchool);
}



public void GroupByFilters(string filter1, string filter2, List<School> school)
{

    PropertyInfo prop1 = typeof(School).GetProperties()
                                      .Where(x => x.Name == filter1)
                                      .First();

    PropertyInfo prop2 = typeof(School).GetProperties()
                                      .Where(x => x.Name == filter2)
                                      .First();                                   
    var grouping = from s in school
                   group s by new {filter1 = prop1.GetValue(s), filter2 = prop2.GetValue(s)} into gr
                   select new {
                    Filter1 = gr.Key.filter1,
                    Filter2 = gr.Key.filter2,
                    TotalGrades = gr.Sum(x => x.Grades),
                    Count = gr.Count(),
                    Average = gr.Average(x => x.Grades)
                   };
    grouping.Dump(); // Linq pad specific 
}

// Define other methods and classes here
public class School{
    public string Student {get;set;}
    public string Teacher {get;set;}
    public string Subject {get;set;}
    public int Grades {get;set;}
}
void Main()
{
var mySchool=新列表{
新学校{Student=“Student A”,Teacher=“Teacher A”,Subject=“Math”,年级=80},
新学校{Student=“Student B”,Teacher=“Teacher A”,Subject=“Math”,年级=65},
新学校{Student=“Student C”,Teacher=“Teacher A”,Subject=“Math”,年级=95},
新学校{Student=“Student A”,Teacher=“Teacher B”,Subject=“History”,年级=80},
新学校{Student=“Student B”,Teacher=“Teacher B”,Subject=“History”,年级=100},
新学校{Student=“Student A”,Teacher=“Teacher C”,Subject=“English”,年级=100},
新学校{Student=“Student C”,Teacher=“Teacher B”,Subject=“English”,年级=100},
新学校{Student=“Student D”,Teacher=“Teacher B”,Subject=“English”,年级=90},
};
GroupByFilters(“教师”、“主题”、我的学校);
GroupByFilters(“主题”、“教师”、我的学校);
}
公共无效GroupByFilters(字符串过滤器1、字符串过滤器2、列表学校)
{
PropertyInfo prop1=typeof(School).GetProperties()
.Where(x=>x.Name==filter1)
.First();
PropertyInfo prop2=typeof(School).GetProperties()
.Where(x=>x.Name==filter2)
.First();
var分组=来自学校的s
按新的{filter1=prop1.GetValue,filter2=prop2.GetValue}将s分组到gr中
选择新的{
过滤器1=gr.Key.Filter1,
过滤器2=gr.Key.Filter2,
TotalGrades=gr.Sum(x=>x.Grades),
Count=gr.Count(),
平均值=gr.平均值(x=>x.等级)
};
grouping.Dump();//特定于Linq焊盘
}
//在此处定义其他方法和类
公立学校{
公共字符串Student{get;set;}
公共字符串教师{get;set;}
公共字符串主题{get;set;}
公共整数等级{get;set;}
}
过滤器1过滤器2总等级计数平均值

数学老师A 240 3 80

教师B历史180 2 90

C英语教师100 1100

B老师英语190295


过滤器1过滤器2总等级计数平均值

数学老师A 240 3 80

历史教师B 180 2 90

英语教师C100 1100


英语教师B 190 2 95

Linq不提供按字段名分组的方法。你必须使用表达式。但是,您可以在运行时通过字段名构建表达式。我在代码中使用了您的建议,但我得到了一些不理解的行为。如果我有:
systemList.GroupBy(“new”(+String.Join(“,”,groupFields)+)”