当前位置:  开发笔记 > 编程语言 > 正文

从集合中删除项目的最佳方法

如何解决《从集合中删除项目的最佳方法》经验,为你挑选了6个好方法。

一旦项目已知,但在C#中从集合中删除项目的最佳方法是什么,但不是它的索引.这是一种方法,但它似乎不够优雅.

//Remove the existing role assignment for the user.
int cnt = 0;
int assToDelete = 0;
foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments)
{
    if (spAssignment.Member.Name == shortName)
    {
        assToDelete = cnt;
    }
    cnt++;
}
workspace.RoleAssignments.Remove(assToDelete);

我真正想做的是找到要按属性删除的项目(在本例中为name),而不循环遍历整个集合并使用另外两个变量.



1> JaredPar..:

如果RoleAssignments是a,List您可以使用以下代码.

workSpace.RoleAssignments.RemoveAll(x =>x.Member.Name == shortName);


是的,它是RemoveAll.我实际上花了时间来检查,验证它是RemoveAll并仍然粘贴在删除.太糟糕的stackoverflow没有内置的编译器:)
AFAIK是就地移除的.
是的,这是一个现场删除.

2> Jon B..:

如果要通过其中一个属性访问集合的成员,可以考虑使用DictionaryKeyedCollection替代.这样您就不必搜索您要查找的项目.

否则,你至少可以这样做:

foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments)
{
    if (spAssignment.Member.Name == shortName)
    {
        workspace.RoleAssignments.Remove(spAssignment);
        break;
    }
}


Jusst以防万一读取此内容并将其应用于删除多个项目的情况,将多个索引保存到一个数组中并使用一个单独的for循环,该循环通过delete数组向后循环以删除项目.
这会导致异常,因为您正在使用它时修改集合...
不,不.这是因为删除该项目后有一个休息时间.

3> Robert Pauls..:

@smaclell问为什么反向迭代在对@ sambo99的评论中更有效率.

有时它更有效率.假设您有一个人员列表,并且您想删除或过滤信用评级<1000的所有客户;

我们有以下数据

"Bob" 999
"Mary" 999
"Ted" 1000

如果我们要向前推进,我们很快就会遇到麻烦

for( int idx = 0; idx < list.Count ; idx++ )
{
    if( list[idx].Rating < 1000 )
    {
        list.RemoveAt(idx); // whoops!
    }
}

在idx = 0时,我们移除Bob,然后将剩余的所有元素移开.下一次通过循环idx = 1,但list [1]现在Ted而不是Mary.我们最终Mary错误地跳过了.我们可以使用while循环,我们可以引入更多变量.

或者,我们只是反向迭代:

for (int idx = list.Count-1; idx >= 0; idx--)
{
    if (list[idx].Rating < 1000)
    {
        list.RemoveAt(idx);
    }
}

已删除项目左侧的所有索引保持不变,因此您不会跳过任何项目.

如果给出要从数组中删除的索引列表,则同样的原则适用.为了保持正确,您需要对列表进行排序,然后将项目从最高索引删除到最低.

现在你可以使用Linq并以简单的方式声明你正在做的事情.

list.RemoveAll(o => o.Rating < 1000);

对于这种删除单个项目的情况,它不再有效地向前或向后迭代.您也可以使用Linq.

int removeIndex = list.FindIndex(o => o.Name == "Ted");
if( removeIndex != -1 )
{
    list.RemoveAt(removeIndex);
}


对于一个简单的List ,如果你需要删除多个项目,反向for循环始终是最有效的方法.它肯定比将数据复制到listToRemove列表更有效.我打赌Linq实现使用相同的技巧.

4> Sam Saffron..:

对于简单的List结构,最有效的方法似乎是使用Predicate RemoveAll实现.

例如.

 workSpace.RoleAssignments.RemoveAll(x =>x.Member.Name == shortName);

原因是:

    Predicate/Linq RemoveAll方法在List中实现,并且可以访问存储实际数据的内部数组.它将移动数据并调整内部数组的大小.

    RemoveAt方法实现非常慢,并将整个底层数据数据复制到一个新数组中.这意味着反向迭代对List无用

如果你在前c#3.0时代被卡住了.你有2个选择.

易于维护的选项.将所有匹配项复制到新列表中,并交换基础列表.

例如.

List list2 = new List() ; 
foreach (int i in GetList())
{
    if (!(i % 2 == 0))
    {
        list2.Add(i);
    }
}
list2 = list2;

要么

棘手的稍微快一点的选项,它涉及在列表不匹配时将列表中的所有数据向下移动然后调整阵列大小.

如果你经常从列表中删除东西,可能另一个结构如HashTable(.net 1.1)或Dictionary(.net 2.0)或HashSet(.net 3.5)更适合这个目的.



5> Colin..:

如果是,ICollection那么你将没有RemoveAll方法.这是一个扩展方法,它将执行此操作:

    public static void RemoveAll(this ICollection source, 
                                    Func predicate)
    {
        if (source == null)
            throw new ArgumentNullException("source", "source is null.");

        if (predicate == null)
            throw new ArgumentNullException("predicate", "predicate is null.");

        source.Where(predicate).ToList().ForEach(e => source.Remove(e));
    }

基于:http: //phejndorf.wordpress.com/2011/03/09/a-removeall-extension-for-the-collection-class/



6> MichaelGG..:

这个系列是什么类型的?如果是List,您可以使用有用的"RemoveAll":

int cnt = workspace.RoleAssignments
                      .RemoveAll(spa => spa.Member.Name == shortName)

(这适用于.NET 2.0.当然,如果你没有新的编译器,你将不得不使用"委托(SPRoleAssignment spa){return spa.Member.Name == shortName;}"而不是lambda语法.)

另一种方法,如果它不是List,但仍然是ICollection:

   var toRemove = workspace.RoleAssignments
                              .FirstOrDefault(spa => spa.Member.Name == shortName)
   if (toRemove != null) workspace.RoleAssignments.Remove(toRemove);

这需要Enumerable扩展方法.(如果您遇到.NET 2.0,可以复制Mono).如果它是一些无法获取项目的自定义集合,但必须采用索引,则其他一些Enumerable方法(如Select)会为您传入整数索引.

推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有