Sha*_*hab 11 .net c# asp.net-mvc ienumerable lambda
我有一个类似的课程
public class Empolyee
{
public string Designation {get ;set;}
public string Discipline {get ;set;}
public int Scale {get ;set;}
public DateTime DOB {get ;set;}
public int Sales {get ;set;}
}
Run Code Online (Sandbox Code Playgroud)
并以可数的说法记录所有员工的记录
List<Employee> Employees;
Run Code Online (Sandbox Code Playgroud)
和一个字符串键列表
var Keys = new List<string>()
{
"Designation",
"Scale",
"DOB"
};
Run Code Online (Sandbox Code Playgroud)
假设列表"Keys"的元素是用户指定的,用户可以指定no或许多关键元素.
现在我想使用列表"Keys"中指定的键对所有"Employees"进行分组,并仅选择"Keys"中指定的属性以及每个组的Sales of Sum.
在我尝试使用的3个解决方案中,以下看起来适用但无法使用它,因为不知道列表"Keys"将如何转换为匿名类型
Employees.GroupBy(e => new { e.Key1, e.Key2, ... })
.Select(group => new {
Key1 = group.Key.Key1,
Key2 = group.Key.Key2,
...
TotalSales = group.Select(employee => employee.Sales).Sum()
});
Run Code Online (Sandbox Code Playgroud)
对于这个问题的最终解决方案,我使用了 @jamespconnor 答案中的编码方法,但字符串作为分组键在我的实际场景中对我没有多大帮助。因此,我使用 @tim-rogers 的数组基本思想作为分组键,并使用 ArrayEqualityComparer 比较数组。
为了获取字符串集合指定的关键属性,我构建了一个静态类,例如
public static class MembersProvider
{
public static IEnumerable<PropertyInfo> GetProperties(Type type, params string[] names)
{
var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty)
.Where(pi => names.Contains(pi.Name))
.Where(pi => pi != null)
.AsEnumerable();
if (names.Count() != properties.Count())
{
throw new InvalidOperationException("Couldn't find all properties on type " + type.Name);
}
return properties;
}
}
Run Code Online (Sandbox Code Playgroud)
并更改了 @jamespconnor 的 GroupByKeys 扩展,有点像
public static class GroupByExtensions
{
public static IEnumerable<IGrouping<object[], TValue>> GroupByKeys<TValue>(this IEnumerable<TValue> values, IEnumerable<string> keys)
{
var properties = MembersProvider.GetProperties(typeof(TValue), keys.ToArray());
var comparer = new ArrayEqualityComparer<object>();
// jamespconnor's string as key approch - off course it will need to return IEnumerable<IGrouping<string, TValue>>
/*return values.GroupBy(v => getters.Aggregate(
"",
(acc, getter) => string.Format(
"{0}-{1}",
acc,
getter.Invoke(v, null).ToString()
)
)
);*/
//objects array as key approch
return values.GroupBy(v => properties.Select(property => property.GetValue(v, null)).ToArray(), comparer);
}
}
Run Code Online (Sandbox Code Playgroud)
由于我还需要选择匿名类型的结果,其中每个“Key”作为其属性和一个附加的“Total”属性,但没有成功,我最终像
// get properties specified by "Keys" collection
var properties = MembersProvider.GetProperties(typeof(Employee), Keys.ToArray());
// Group and Select
var SalesSummary = Employees
.GroupByKeys(Keys.ToArray())
.Select(g =>
properties.Aggregate(
new Dictionary<string, object>() { { "TotalSales", g.Select(employee => employee.Sales).Sum() } },
(dictionary, property) => {
dictionary.Add(property.Name, property.GetValue(g.FirstOrDefault(), null));
return dictionary;
}
)
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2421 次 |
| 最近记录: |