C# LINQ-具有多个组中的项目的groupBy

C# LINQ-具有多个组中的项目的groupBy,c#,linq,C#,Linq,我有一个对象列表,它有两个属性,比如a和ba是一个类似于以下的枚举: [Flags] enum MyEnum { first = 1, second = 2, third = 4, fourth = 8 }; b是一个无符号整数,它是一个掩码(MyEnum标志的组合) 现在我需要用它们的a对每个对象求和-这意味着如果obj.a=first | third一个对象可以求和两次,而我似乎无法对它们进行groupBy。有没有不同的方法来求和 很抱歉,我没有分享我的

我有一个对象列表,它有两个属性,比如
a
b
a
是一个类似于以下的枚举:

[Flags] enum MyEnum
{
    first  = 1,
    second = 2,
    third  = 4,
    fourth = 8
};
b
是一个无符号整数,它是一个掩码(MyEnum标志的组合)

现在我需要用它们的
a
对每个对象求和-这意味着如果
obj.a=first | third
一个对象可以求和两次,而我似乎无法对它们进行
groupBy
。有没有不同的方法来求和

很抱歉,我没有分享我的代码,但我不能。我可以告诉你,我只是在一些if-else块中使用foreach实现的,但我认为我应该学习如何在Linq中实现它

编辑: 我想我不清楚。我想通过枚举对对象求和,这意味着如果我有:

obj1.a = first, obj1.b = 5
obj2.a = first | second, obj2.b = 3
然后输出将是

first sum = 8
second sum = 3

尝试使用HasFlag和GetValues提取特定枚举值的所有标志:

var objs = new[] { new { a = MyEnum.first | MyEnum.second }, new { a = MyEnum.first }... };
var enumValues = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().ToArray();

// first, use SelectMany to create a sequence with one instance of each object for
// each flag value in it's a
var grouped = objs.SelectMany(
        o => enumValues.Where(flag => o.a.HasFlag(flag))
            .Select(v => new { o, flag })
    )
    // then group by the extracted flag value
    // the element selector (t => t.o) gets us back to an IGrouping of o's (dropping the extra flag property
    .GroupBy(t => t.flag, t => t.o);

 // finally, we can get sums by a as follows:
 var sumsByA = grouped.ToDictionary(g => g.Key, g => g.Sum(o => o.b));
var objs=new[]{new{a=MyEnum.first | MyEnum.second},new{a=MyEnum.first}…};
var enumValues=Enum.GetValues(typeof(MyEnum)).Cast().ToArray();
//首先,使用SelectMany为每个对象创建一个序列,每个对象有一个实例
//其中的每个标志值都是一个
var group=objs.SelectMany(
o=>enumValues.Where(标志=>o.a.HasFlag(标志))
.Select(v=>new{o,flag})
)
//然后根据提取的标志值进行分组
//元素选择器(t=>t.o)让我们回到o的i组(删除额外的flag属性)
.GroupBy(t=>t.flag,t=>t.o);
//最后,我们可以通过a得到如下总和:
var-sumsByA=grouped.ToDictionary(g=>g.Key,g=>g.Sum(o=>o.b));

给定一个
MyEnum
和一个
MyClass

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

class MyClass
{
    public MyEnum MyEnum;
    public uint Value;
}
还有一些价值观

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 },
};
此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) };
该表达式以enum(
enum.GetValues(typeof(MyEnum)).Cast()
)的值开始,然后为每个值“保存”具有相同
MyEnum
let temp=mcs.Where(q=>q.MyEnum.haskag(p))(q=>q.value.ToArray())的
MC的值在
temp
中,跳过空的
temp
where temp.Length>0
)并对剩余的
temp
选择新的{MyEnum=p,sum=temp.sum(q=>q)}
)。注意,如果使用
uint
,则必须使用
temp.sum(q=>q)
,但是使用
int
可以使用
temp.Sum()
(或者可以使用
temp.Sum(q=>q)

另一种方法是通过双重
from
分组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) };
var ret=来自Enum.GetValues(typeof(MyEnum)).Cast()中的p
从mcs中的q
其中q.MyEnum.hassflag(p)
将q值按p分组为r
选择新的{MyEnum=r.Key,Sum=r.Sum(p=>p)};

这可能相当于使用ChaseMedallion建议的
SelectMany
(编译器将来自
的双
转换为
SelectMany

你能提供预期的结果吗?你的问题对我来说不是很清楚。你的问题仍然不清楚。如果我们有
obj3=first | second | third;
的和是什么?它们可以是
first sum=15
second sum=8
third sum=3
fourth sum=7
fifth sum=8
,吗,
sixth sum=14
?@KingKing完全正确。我按枚举值求和,因此,如果对象在值字段的枚举中有第一个|第二个|第三个和3个,那么3将被添加到第一个、第二个和第三个的总和中。谢谢你的回答,非常好并且解释过了,我会尽快尝试,真的谢谢你。非常解释过了,也很好用。excel有力的回答
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) };