一旦项目已知,但在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);
Run Code Online (Sandbox Code Playgroud)
我真正想做的是找到要按属性删除的项目(在本例中为name),而不循环遍历整个集合并使用另外两个变量.
Jar*_*Par 130
如果RoleAssignments是a,List<T>您可以使用以下代码.
workSpace.RoleAssignments.RemoveAll(x =>x.Member.Name == shortName);
Run Code Online (Sandbox Code Playgroud)
Jon*_*n B 26
如果要通过其中一个属性访问集合的成员,可以考虑使用Dictionary<T>或KeyedCollection<T>替代.这样您就不必搜索您要查找的项目.
否则,你至少可以这样做:
foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments)
{
if (spAssignment.Member.Name == shortName)
{
workspace.RoleAssignments.Remove(spAssignment);
break;
}
}
Run Code Online (Sandbox Code Playgroud)
Rob*_*son 22
@smaclell问为什么反向迭代在对@ sambo99的评论中更有效率.
有时它更有效率.假设您有一个人员列表,并且您想删除或过滤信用评级<1000的所有客户;
我们有以下数据
"Bob" 999
"Mary" 999
"Ted" 1000
Run Code Online (Sandbox Code Playgroud)
如果我们要向前推进,我们很快就会遇到麻烦
for( int idx = 0; idx < list.Count ; idx++ )
{
if( list[idx].Rating < 1000 )
{
list.RemoveAt(idx); // whoops!
}
}
Run Code Online (Sandbox Code Playgroud)
在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);
}
}
Run Code Online (Sandbox Code Playgroud)
已删除项目左侧的所有索引保持不变,因此您不会跳过任何项目.
如果给出要从数组中删除的索引列表,则同样的原则适用.为了保持正确,您需要对列表进行排序,然后将项目从最高索引删除到最低.
现在你可以使用Linq并以简单的方式声明你正在做的事情.
list.RemoveAll(o => o.Rating < 1000);
Run Code Online (Sandbox Code Playgroud)
对于这种删除单个项目的情况,它不再有效地向前或向后迭代.您也可以使用Linq.
int removeIndex = list.FindIndex(o => o.Name == "Ted");
if( removeIndex != -1 )
{
list.RemoveAt(removeIndex);
}
Run Code Online (Sandbox Code Playgroud)
Sam*_*ron 10
对于简单的List结构,最有效的方法似乎是使用Predicate RemoveAll实现.
例如.
workSpace.RoleAssignments.RemoveAll(x =>x.Member.Name == shortName);
Run Code Online (Sandbox Code Playgroud)
原因是:
如果你在前c#3.0时代被卡住了.你有2个选择.
例如.
List<int> list2 = new List<int>() ;
foreach (int i in GetList())
{
if (!(i % 2 == 0))
{
list2.Add(i);
}
}
list2 = list2;
Run Code Online (Sandbox Code Playgroud)
要么
如果你经常从列表中删除东西,可能另一个结构如HashTable(.net 1.1)或Dictionary(.net 2.0)或HashSet(.net 3.5)更适合这个目的.
如果是,ICollection那么你将没有RemoveAll方法.这是一个扩展方法,它将执行此操作:
public static void RemoveAll<T>(this ICollection<T> source,
Func<T, bool> 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));
}
Run Code Online (Sandbox Code Playgroud)
基于:http: //phejndorf.wordpress.com/2011/03/09/a-removeall-extension-for-the-collection-class/
这个系列是什么类型的?如果是List,您可以使用有用的"RemoveAll":
int cnt = workspace.RoleAssignments
.RemoveAll(spa => spa.Member.Name == shortName)
Run Code Online (Sandbox Code Playgroud)
(这适用于.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);
Run Code Online (Sandbox Code Playgroud)
这需要Enumerable扩展方法.(如果您遇到.NET 2.0,可以复制Mono).如果它是一些无法获取项目的自定义集合,但必须采用索引,则其他一些Enumerable方法(如Select)会为您传入整数索引.
| 归档时间: |
|
| 查看次数: |
133553 次 |
| 最近记录: |