Linq-选择中的优选值

时间:2018-02-28 07:57:29

标签: c# 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();

为什么我要避免上述情况?因为我对很多属性都有相同的逻辑。

3 个答案:

答案 0 :(得分:3)

使用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");
}

答案 1 :(得分:2)

您可以检查是否存在与第一个条件匹配的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 :(得分:1)

使用2种类型的简单循环,在循环体中使用Linq查询,或围绕Linq查询构建函数并使用不同类型调用它。例如:

var salary = GetSalary(persons, "Manager");
if (salary == 0) salary = GetSalary(persons, "MiddleManager");