LINQ - groupBy包含多个Group中的项目

No *_*ame 5 c# linq

我有一个对象列表,有两个属性,让我们说a和b.a像Enum一样:

[Flags] enum MyEnum
{
    first  = 1,
    second = 2,
    third  = 4,
    fourth = 8
};
Run Code Online (Sandbox Code Playgroud)

b是无符号整数,它是一个掩码(MyEnum标志的组合).

现在我需要通过它们对每个对象求和a- 这意味着如果一个对象可以总结两次,obj.a = first | third而且我似乎无法groupBy对它们做一个.是否有不同的方式来总结它们?

对不起,我不分享我的代码,但我不能.我可以告诉你,我只是在一些if - else块中使用foreach,但我想我应该学习如何在Linq中做到这一点

编辑: 我想我不清楚.我想通过Enum总结对象,这意味着如果我有:

obj1.a = first, obj1.b = 5
obj2.a = first | second, obj2.b = 3
Run Code Online (Sandbox Code Playgroud)

然后输出将是

first sum = 8
second sum = 3
Run Code Online (Sandbox Code Playgroud)

xan*_*tos 3

给定 aMyEnum和 aMyClass

[Flags]
enum MyEnum
{
    first = 1,
    second = 2,
    third = 4,
    forth = 8
}

class MyClass
{
    public MyEnum MyEnum;
    public uint Value;
}
Run Code Online (Sandbox Code Playgroud)

和一些价值观

var mcs = new[] { 
    new MyClass { MyEnum = MyEnum.first | MyEnum.third, Value = 10 },
    new MyClass { MyEnum = MyEnum.second, Value = 20 },
    new MyClass { MyEnum = MyEnum.first, Value = 100 },
};
Run Code Online (Sandbox Code Playgroud)

此 LINQ 表达式将为枚举的每个值返回这些值的总和。

var ret = from p in Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>() 
              select new { MyEnum = p, Sum = mcs.Where(q => q.MyEnum.HasFlag(p)).Sum(q => q.Value) };
Run Code Online (Sandbox Code Playgroud)

MyEnum.fourth请注意,即使对于value ,它也会返回一个“行” 0。

该表达式以枚举 ( ) 的值开始,然后对于每个值,它对具有相同( )Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>()的值求和mcsMyEnummcs.Where(q => q.MyEnum.HasFlag(p)).Sum(q => q.Value)

如果要排除未使用的枚举值:

var ret = from p in Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>()
          let temp = mcs.Where(q => q.MyEnum.HasFlag(p)).Select(q => q.Value).ToArray()
          where temp.Length > 0
          select new { MyEnum = p, Sum = temp.Sum(q => q) };
Run Code Online (Sandbox Code Playgroud)

该表达式以枚举 ( ) 的值开始,然后对于每个值,它“保存”中具有相同( )Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>()的值,跳过空值 ( ) 并对剩余的值求和( )。请注意,如果您使用 an 则必须使用,但使用 an则可以使用(或者可以使用)。mcsMyEnumlet temp = mcs.Where(q => q.MyEnum.HasFlag(p)).Select(q => q.Value).ToArray()temptempwhere temp.Length > 0tempselect new { MyEnum = p, Sum = temp.Sum(q => q) }uinttemp.Sum(q => q)inttemp.Sum()temp.Sum(q => q)

另一种方法是通过 doublefrom和 agroup by

var ret = from p in Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>()
          from q in mcs 
          where q.MyEnum.HasFlag(p)
          group q.Value by p into r
          select new { MyEnum = r.Key, Sum = r.Sum(p => p) };
Run Code Online (Sandbox Code Playgroud)

它可能相当于使用SelectManyChaseMedallion 所建议的( doublefrom由编译器转换为 a SelectMany)