我正在尝试使用Linq对List<Person>
进行分组。
var grouped = personList.GroupBy(x => new { x.Forename, x.Age })
.Select(x => new { Description = x.Key, Count = x.Count() });
如何使来自变量的属性成为变量?
var groupByProperties = new string[] { "Forename", "Age" };
personList.GroupBy(x => new { ............ })
.Select(x => new { Description = x.Key, Count = x.Count() });
groupByProperties
将来自网页上的用户输入(<select multiple>
)。
我无法理解ExpandoObject
或dynamic
的正确语法,并且不确定我是否需要在此使用反射。
Person类可能类似于:
public class Person
{
public string Forename { get; set; }
public string Surname { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
}
结果作为JSON传回UI(网页),从中生成数据网格。我将使用javascript循环返回的Description对象,并从中生成网格。
答案 0 :(得分:1)
感谢potehin143指出我对ScottGu的优秀Linq Dynamic Query Library,我已经设法让一些东西在运行。
我最后得到了一个很好的单行(尽管有一些奇怪的语法)。
var fieldsToGroupBy = new string[] { "Forename", "Age" };
var grouped = personList.GroupBy( "new ( "+fieldsToGroupBy.ToCommaSeparatedString("it.")+" )", "it" )
.Select("new ( it.Key as Description, it.Count() as Count )");
response.Data = (dynamic)grouped;
ToCommaSeparatedString()
是一种简单的扩展方法,可将[&#34; Forename&#34;,&#34; Age&#34;]更改为&#34; it.Forename,it.Age&#34;。
之前的解决方案(下面)并没有以我希望的格式返回数据。 (它在组中返回所有数据,而不仅仅是摘要。)感谢Mitsu提供此解决方案(博客文章here和here)。
var groupByProperties = new string[] { "Forename", "Age" };
var grouped = personList.GroupByMany(groupByProperties);
Linq动态查询库做得太多,甚至无法发布片段。 GroupByMany方法:
public static IEnumerable<GroupResult> GroupByMany<TElement>(
this IEnumerable<TElement> elements, params string[] groupSelectors)
{
var selectors =
new List<Func<TElement, object>>(groupSelectors.Length);
foreach (var selector in groupSelectors)
{
LambdaExpression l =
DynamicExpression.ParseLambda(
typeof(TElement), typeof(object), selector);
selectors.Add((Func<TElement, object>)l.Compile());
}
return elements.GroupByMany(selectors.ToArray());
}
public static IEnumerable<GroupResult> GroupByMany<TElement>(
this IEnumerable<TElement> elements,
params Func<TElement, object>[] groupSelectors)
{
if (groupSelectors.Length > 0)
{
var selector = groupSelectors.First();
//reduce the list recursively until zero
var nextSelectors = groupSelectors.Skip(1).ToArray();
return
elements.GroupBy(selector).Select(
g => new GroupResult
{
Key = g.Key,
Count = g.Count(),
Items = g,
SubGroups = g.GroupByMany(nextSelectors)
});
}
else
return null;
}
答案 1 :(得分:-1)
试试这个
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication29
{
class Program
{
static void Main(string[] args)
{
List<Person> personList = new List<Person>();
string[] groups = { "Forename", "Surname" };
var grouped = personList.GroupBy(x => new object[] { Grouper(x, groups) })
.Select(x => new { Description = x.Key, Count = x.Count() });
}
static object[] Grouper(Person person, string[] groups)
{
List<object> results = new List<object>();
foreach (string group in groups)
{
switch (group)
{
case "Forename" :
results.Add(person.Forename);
break;
case "Surname":
results.Add(person.Surname);
break;
case "Age":
results.Add(person.Age);
break;
case "Gender":
results.Add(person.Gender);
break;
}
}
return results.ToArray();
}
}
public class Person
{
public string Forename { get; set; }
public string Surname { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
}
}