Linq-选择中的优选值
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linq-选择中的优选值相关的知识,希望对你有一定的参考价值。
如果我有以下型号:
Public class Person {
public string Name {get; set;}
public string Type {get; set;}
public int Salary {get; set;}
}
我有一份人员名单,List<Person> persons = new List<Person>();
现在我想要最常见的经理薪水,如果不存在,我想要MiddleManagers最常见的薪水。
我尝试了以下方法:
int salary= persons.Where(x => x.Type=="Manager" || x.Type=="MiddleManager")
.GroupBy(pr => pr.Salary)
.OrderByDescending(g => g.Count())
.Select(x => x.Key)
.FirstOrDefault();
但这将返回经理和MiddleManagers中最常见的薪水,有没有办法实现上述目标而不会:
int salary= persons.Where(x => x.Type=="Manager")
.GroupBy(pr => pr.Salary)
.OrderByDescending(g => g.Count())
.Select(x => x.Key)
.FirstOrDefault();
if(salary==0)
salary= persons.Where(x => x.Type=="MiddleManager")
.GroupBy(pr => pr.Salary)
.OrderByDescending(g => g.Count())
.Select(x => x.Key)
.FirstOrDefault();
为什么我要避免上述情况?因为我对许多属性都有相同的逻辑。
答案
使用C#本地函数:
ILookup<string, Person> personsByType = persons.ToLookup(person => person.Type);
double getSalary(string type)
{
return personsByType[type]
.GroupBy(pr => pr.Salary)
.OrderByDescending(g => g.Count())
.Select(x => x.Key)
.FirstOrDefault();
}
double salary= getSalary("Manager");
if (salary == 0)
{
salary = getSalary("MiddleManager");
}
请注意,如果只有在没有给定类型的人的情况下才获得0工资,因为我认为某人不能拥有0工资。所以你可以这样做:
double? getSalary(string type)
{
IEnumerable<Person> selectedPeople = personsByType[type];
return selectedPeople.Any() ? selectedPeople
.GroupBy(pr => pr.Salary)
.OrderByDescending(g => g.Count())
.Select(x => x.Key)
.First()
: null;
}
double? salary= getSalary("Manager");
if (!salary.HasValue)
{
salary = getSalary("MiddleManager");
}
另一答案
您可以检查是否存在与第一个条件匹配的Any项目,并将Type
分配给将在查询中使用的字符串变量:
string property = persons.Any(x => x.Type == "Manager") ? "Manager" : "MiddleManager";
int salary = persons.Where(x => x.Type == property)
.GroupBy(pr => pr.Salary)
.OrderByDescending(g => g.Count())
.Select(x => x.Key)
.FirstOrDefault();
在List<Person>
中确切地说明这种分组逻辑的一种通用方法可能如下所示:
public int mostCommonSalary(List<Person> collection, params string [] types)
{
foreach (var type in types)
{
if (collection.Any(x => x.Type == type))
{
return collection.Where(x => x.Type == type)
.GroupBy(pr => pr.Salary)
.OrderByDescending(g => g.Count())
.Select(x => x.Key)
.FirstOrDefault();
}
}
// nothing found
return -1;
}
您可以根据需要使用多种类型。它的第一场比赛将被退回:
int salary = mostCommonSalary(persons, "Manager", "MiddleManager", "MicroManager", "NanoManager");
通过传递您想要过滤的属性,可以使它更通用或更通用:
public int mostCommonSalaryGeneral<T>(List<Person> collection,
Func<Person, T> filterFunc, params T[] types)
{
foreach (var type in types)
{
if (collection.Any(x=> filterFunc(x).Equals(type)))
{
return collection.Where(x=> filterFunc(x).Equals(type))
.GroupBy(pr => pr.Salary)
.OrderByDescending(g => g.Count())
.Select(x => x.Key)
.FirstOrDefault();
}
}
// nothing found
return -1;
}
这样您就可以按所选属性进行过滤,并调用如下方法:
int salary = mostCommonSalaryGeneral(persons, p => p.Type, "Manager", "MiddleManager", "MicroManager", "NanoManager");
int salary = mostCommonSalaryGeneral(persons, p => p.Name, "Max", "Maxine", "Masud");
int salary = mostCommonSalaryGeneral(persons, p => p.SomeID, 1234, 3456);
另一答案
使用2种类型的简单循环,在循环体中使用Linq查询,或围绕Linq查询构建函数并使用不同类型调用它。例:
var salary = GetSalary(persons, "Manager");
if (salary == 0) salary = GetSalary(persons, "MiddleManager");
以上是关于Linq-选择中的优选值的主要内容,如果未能解决你的问题,请参考以下文章
错误 3002:映射片段中的问题 | c# linq 到实体