基于条件查找常用项列表的有效方法

时间:2015-12-19 13:40:32

标签: c# collections

我有权限列表列表,即List<List<Permission>> permisionLists,每个权限都有名为HasPermission的属性。 除权限项的HasPermission属性为true / false之外,每个权限列表都相同。 在permisionLists中查找所有HasPermission设置为false的权限列表的最有效方法是什么?

我必须只找到每个List中值设置为false的权限。

public class Permission
{
    public Guid Id { get; set; }
    public string Action { get; set; }
    public bool HasPermission { get; set; }
}

我试过下面的代码,但没有运气,

disabledPermissions = from permisions in permisionLists
    from permission in permisions
    where permisionLists.All(l => l.Any(o => o.HasPermission ==false))
    orderby permission.HasPermission
    select permission;

3 个答案:

答案 0 :(得分:1)

再次编辑:这应该让您了解如何过滤列表以搜索相同的ID。这可能不是最好的以绩效为导向的方法,但它应该给你一个想法:

permisionLists.ForEach(permissions => permissions.Where(p => !p.HasPermission).ToList().ForEach(permission =>
{
    if (!permisionLists.Where(permissionList => permissionList.Where(p => p.Id == permission.Id).FirstOrDefault().HasPermission).Any())
    {
        disabledPermissions.Add(permission);
    }
}));

ForEach方法为列表中的每个项执行lambda表达式。这只会明确过滤列表中HasPermission设置为false的项目。

答案 1 :(得分:0)

您在问题中使用“有效”一词。您将需要询问列表的问题,并确保仅重新计算列表内容更改。

我会考虑像这样创建一个新类;

public class PermissionCollection : Collection<Permission>
{
}

重写InsertItem,RemoveItem方法等,如this MSDN page的示例2所示。在任何编辑

上设置像collectionDirty这样的私有布尔值为true

然后添加另一个属性,如

public bool HasAnyPermissions
{
    get
    {
            if (collectionDirty) {
                // recalculate here
                cachedAnswer = ...;
                collectionDirty = false;
            }

           Return cachedAnswer;
    }
}

这为您提供了一种非常有效的方法来确保您没有执行当前建议所遭受的O(n ^ 2)搜索。

答案 2 :(得分:0)

如果我理解你的问题,以下将是实现线性时间复杂度目标的一种非常有效的方法

var itemMap = new Dictionary<Guid, Permission>();
foreach (var list in permissionLists)
{
    foreach (var item in list)
    {
        Permission other;
        if (!itemMap.TryGetValue(item.Id, out other) || (item.HasPermission && !other.HasPermission))
            itemMap[item.Id] = item;
    }
}
var result = itemMap.Values.Where(item => !item.HasPermission).ToList();

使用Linq可以实现同样的效果,但由于分组存储分配会占用更多空间

var result =
    (from list in permissionLists
     from item in list
     group item by item.Id into g
     where !g.Any(item => item.HasPermission)
     select g.First()).ToList();

我个人更喜欢前者(非Linq)。