C#LINQ查询 - 从集合(嵌套组?)中提取多个组



我有一个名为Person的类,有2个属性年龄和名称

我试图将人们分为3个不同的年龄组。

我希望我的最终结果是这样的:

YoungGroup (<20 y old):
    Person1Name, Age
    Person4Name, Age
    Person3Name, Age
AdultGroup (20> y <40 old):
    Person2Name, Age
    Person7Name, Age
    Person5Name, Age
SeniorGroup (40> y old):
    Person6Name, Age
    Person8Name, Age
    Person9Name, Age

我只想使用组子句(如果可能的话,也没有加入?(

这就是我尝试的

var multiplegrps = from p in people
                   group p by p.Age into groups
                   let age = groups.Key
                   select new
                   {
                       YoungGroup = from p in groups
                                    where age <= 20
                                    group p by p.Age,
                       AdultGroup = from p in groups
                                    where age >= 21 && age <= 40
                                    group p by p.Age,
                      SeniorGroup = from p in groups
                                    where age >= 41
                                    group p by p.Age
                   };

它是有效的,或者我实际上不知道如何打印它:

foreach (var item in multiplegrps)
{
    foreach (var i in item.YoungGroup)
    {
        Console.WriteLine($"{i.Key}");
    }
}

我确实得到了正确的键,但是我无法访问这些名称,我必须为每个组编写3个内部foreach

P.S。我只想使用纯查询来完成,没有lambdas没有新的扩展方法

P.S。我解决了它,并从@khoroshevj获得了有关使用多个三元操作员的想法,就像:

一样简单
        var peopleMultiGrouping = from p in people
                                  let ageSelection =
                                        p.Age < 20
                                            ? "Young" 
                                            : p.Age >= 20 && p.Age <= 40
                                                ? "Adult" 
                                                : "Senior"
                                  group p by ageSelection;
        foreach (var p in peopleMultiGrouping)
        {
            Console.WriteLine($"{p.Key}");
            foreach (var i in p)
            {
                Console.WriteLine($" {i.Age}");
            }
        }

您可以做这样的事情

var multiplegrps =
    from p in people
    let groupName = GetGroupName(p.Age)
    group p by groupName
    into groups
    group groups by groups.Key;
foreach (var group in multiplegrps)
{
    foreach (var member in group.SelectMany(i => i))
    {
        Console.WriteLine($"{group.Key}, {member.Age}, {member.Name}");
    }
}
private static string GetGroupName(int age)
{
    return age <= 20
        ? "YoungGroup"
        : age <= 40
            ? "AdultGroup"
            : "SeniorGroup";
}

您的解决方案确实可以按照您的预期工作。问题是您打印结果的方式。

在第二级循环中,i是类型IGrouping<int, Person>,基本代表具有公共密钥的对象集合。

您在访问它时显然具有Key属性,但没有Value属性。

您可以执行另一个嵌套循环以迭代IGrouping,然后可以访问完整的Person属性,或者如果您只想将其保持在两级环路上,则可以使用item.YoungGroup将CC_7弄平进入IEnumerable<Person>并像这样迭代:

foreach (var item in multiplegrps)
{
       foreach (var person in item.YoungGroup.SelectMany(x => x))
       {
            Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");
       }
}

您似乎正在寻找的最终分组输出是3个离散的人,即年轻,成人和高级人士。

对我来说,对每个人进行分类是有意义的每个人都可以分为年龄段:

var classifiedPersons = people
   .Select(p => new{
       Person = p, 
       AgeClassification = 
          p.age <= 20
            ? "Young"
            : p.age <= 40
                ? "Adult"
                : "Senior" 
    })
   .GroupBy(cp => cp.AgeClassification)
   .ToDictionary(grp => grp.Key, grp => grp.Select(g => g.Person));

(您可以使用除字符串以外的其他分类,例如在这里枚举(

现在,您可以通过" Young","成人"one_answers"高级"钥匙访问三组。

您可以像这样一般打印出群体:

foreach (var group in classifiedPersons)
{
    Console.WriteLine($"Group: {group.Key}:");
    foreach (var person in group.Value)
    {
        Console.WriteLine($"  - {person.Name}:");
    }
}

看来您想要一个包含所有三个组的匿名对象,例如:

var allGroupsInOneObject = new {
   YoungPeople = classifiedPersons["Young"],
   AdultPeople = classifiedPersons["Adult"],
   SeniorPeople = classifiedPersons["Senior"]
};

一个警告 - 在通过字典键访问组之前,您可能只需要确保组中有任何人。

----------
foreach (var item in multiplegrps)
            {
                foreach (var yItem in item.YoungGroup)
                {
                    if (item.YoungGroup.Count() > 0 && yItem.ElementAt(0) != null)
                    {
                        Console.WriteLine("Young : " + yItem.ElementAt(0).Name);
                    }
                }
                foreach (var aItem in item.AdultGroup)
                {
                    if (item.AdultGroup.Count() > 0 &&aItem.ElementAt(0) != null)
                    {
                        Console.WriteLine("Adult : " + aItem.ElementAt(0).Name);
                    }
                }
                foreach (var sItem in item.SeniorGroup)
                {
                    if (item.SeniorGroup.Count() > 0 &&sItem.ElementAt(0) != null)
                        {
                            Console.WriteLine("Senior : " + sItem.ElementAt(0).Name);
                        }
                }
            }

我解决了它,并从@khoroshevj获得了有关使用多个三元运算符的想法,就像:

一样简单
        var peopleMultiGrouping = from p in people
                                  let ageSelection =
                                        p.Age < 20
                                        ? "Young" 
                                        : p.Age >= 20 && p.Age <= 40
                                            ? "Adult" 
                                            : "Senior"
                                  group p by ageSelection;
        foreach (var p in peopleMultiGrouping)
        {
            Console.WriteLine($"{p.Key}");
            foreach (var i in p)
            {
                Console.WriteLine($" {i.Age}");
            }
        }

您是否尝试过:

var multiplegrps = people.GroupBy(x=> x.age)
                         .ToDictionary(x=>x.Key,
                                       x=>x.Select(y=>new {  
                                                 YoungGroup=y.where(z=>z.age<= 20), 
                                                 AdultGroup=y.Where(z=>z.age >=21 && a.age <= 40), 
                                                SeniorGroup=y.Where(z=> z.age >=41) 
                                                          });

这只是一个主意,没有尝试过...

最新更新