使用Linq分组的位运算
我有一个类似于使用Linq分组的位运算,linq,bit-manipulation,Linq,Bit Manipulation,我有一个类似于 public class PermList { public int UserId { get; set; } public int GroupId { get; set; } public int ModuleId { get; set; } public int BitMaskedPermission { get; set; } public List<PermList> TestData() {
public class PermList
{
public int UserId { get; set; }
public int GroupId { get; set; }
public int ModuleId { get; set; }
public int BitMaskedPermission { get; set; }
public List<PermList> TestData()
{
List<PermList> theList = new List<PermList>();
PermList sample1 = new PermList {BitMaskedPermission = 15, GroupId = 3, ModuleId = 2, UserId = 1};
theList.Add(sample1);
PermList sample2 = new PermList { BitMaskedPermission = 2, GroupId = 3, ModuleId = 1, UserId = 1 };
theList.Add(sample2);
PermList sample3 = new PermList { BitMaskedPermission = 48, GroupId = 2, ModuleId = 2, UserId = 1 };
theList.Add(sample3);
return theList;
}
}
公共类列表
{
public int UserId{get;set;}
public int GroupId{get;set;}
public int ModuleId{get;set;}
公共整数位掩码权限{get;set;}
公共列表TestData()
{
列表列表=新列表();
PermList sample1=新的PermList{BitMaskedPermission=15,GroupId=3,ModuleId=2,UserId=1};
添加列表(样本1);
PermList sample2=新的PermList{BitMaskedPermission=2,GroupId=3,ModuleId=1,UserId=1};
添加列表(样本2);
PermList sample3=新的PermList{BitMaskedPermission=48,GroupId=2,ModuleId=2,UserId=1};
添加列表(样本3);
返回列表;
}
}
我想使用分组模块ID向位掩码许可证申请或。这是我想要的
如何使用Linq实现这一点
TIA.可能是这样的:
PermList p=new PermList();
var result= (
from test in p.TestData()
group test by new{test.UserId,test.ModuleId} into g
select new
{
g.Key.UserId,
g.Key.ModuleId,
BitMaskedPermission= g.Sum (x =>x.BitMaskedPermission )
}
);
也许是这样的:
PermList p=new PermList();
var result= (
from test in p.TestData()
group test by new{test.UserId,test.ModuleId} into g
select new
{
g.Key.UserId,
g.Key.ModuleId,
BitMaskedPermission= g.Sum (x =>x.BitMaskedPermission )
}
);
如果要执行的聚合操作不是内置操作之一(
Sum
,Max
等),则必须转到Aggregate
,它更详细,但功能也更强大。给你,你想要什么
var data = TestData();
var grouped =
from permList in data
group permList by new { permList.UserId, permList.ModuleId } into g
select new { // or a named class if you have one
g.Key.UserId,
g.Key.ModuleId,
BitMaskedPermission
= g.Aggregate(0, (acc, curr) => acc | curr.BitMaskedPermission)
};
在这里,我们传递一个函数,该函数接受当前值和当前值,并对它们进行位运算以获得当前累加器值
如果您更喜欢方法链接语法,它将如下所示(由提供):
如果要执行的聚合操作不是内置操作之一(
Sum
,Max
等),则必须转到Aggregate
,它更详细,但功能也更强大。给你,你想要什么
var data = TestData();
var grouped =
from permList in data
group permList by new { permList.UserId, permList.ModuleId } into g
select new { // or a named class if you have one
g.Key.UserId,
g.Key.ModuleId,
BitMaskedPermission
= g.Aggregate(0, (acc, curr) => acc | curr.BitMaskedPermission)
};
在这里,我们传递一个函数,该函数接受当前值和当前值,并对它们进行位运算以获得当前累加器值
如果您更喜欢方法链接语法,它将如下所示(由提供):
这确实适用于示例数据,但假设
BitMaskedPermission
对于ModuleId
2
行都是15
:此代码将给出30
,这将是错误的。sum不一定能满足您的要求。如果有两个位掩码都是32,那么组合它们的结果应该是32,而不是64。这确实适用于样本数据,但假设位掩码许可
对于模块ID
2行都是15
:此代码将给出30
,这是错误的。sum不一定会做你想做的事。如果你有两个位掩码都是32,那么组合它们的结果应该是32,而不是64,因为我用另一种形式做了这件事,所以我给出了与之等价的方法:PermList.TestData().GroupBy(x=>new{x.UserId,x.ModuleId})。选择(x=>new{x.Key.UserId,x.Key.ModuleId,mask=x.Aggregate(0,(acc,curr)=>acc | curr.BitMaskedPermission)})
。如果您愿意,请随时将其编辑到您的答案中(或者修改和编辑或其他我认为您的聚合是错误的内容)。我认为您需要g.Aggregate(0,(acc,curr)=>acc | curr.BitMaskedPermission)(即将累加器默认值设置为0,并使用位掩码,而不是PermList对象。@Chris感谢您的捕获。顺便说一句,如果您愿意使用序列的第一个元素作为初始累加器值(如我们所示),你。事实上,我刚刚检查过,你确实需要初始累加器。如果没有它,则使用序列的第一个元素,但这当然是一个PermList对象,而我们需要一个int。虽然AakashM的答案正确指出了解决方案并对聚合进行了很好的解释,但需要Chris的更新来解决问题。谢谢。还有因为我是以另一种形式做这件事的,所以我给出了与之等价的方法:PermList.TestData().GroupBy(x=>new{x.UserId,x.ModuleId})。选择(x=>new{x.Key.UserId,x.Key.ModuleId,mask=x.Aggregate(0,(acc,curr)=>acc | curr.BitMaskedPermission)
。如果需要,请随意编辑到您的答案中(或者修改和编辑或者其他我认为你的聚合是错误的。你需要g.Aggregate(0,(acc,curr)=>acc | curr.BitMaskedPermission)我认为(即将累加器默认值设置为0,并使用位掩码,而不是PermList对象。@Chris感谢您的捕获。顺便说一句,如果您愿意使用序列的第一个元素作为初始累加器值(如我们所示),你。事实上,我刚刚检查过,你确实需要初始累加器。如果没有它,则使用序列的第一个元素,但这当然是一个PermList对象,而我们需要一个int。虽然AakashM的答案正确地指出了解决方案并对聚合进行了很好的解释,但需要Chris的更新来解决问题。谢谢。