我正在尝试制作一个有效的删除方法来处理列表。这种情况如下:
说...我有一个(可能)庞大的名单:
Alex Smith
Anna Hobb
Bertie Blackman
Bill Clinton
David Smith
David Warner
George Jung
George Washington
William Wobbits
让我们说这是List<Person>
,其中Person具有属性FirstName
和LastName
。如示例中所示,两个人可能共享相同的FirstName。我需要做的是查看列表并删除所有Davids,例如。
我正在循环查找所有davids,添加到列表DeletePerson
,然后再次循环查看每个DeletePerson
并删除。我相信会有更有效的方法吗?效率在这个应用程序中并不重要,但它似乎是一个漫长的方式来做到这一点,我想,因为在第一个名字的字母D后我们知道我们将不再添加到DeletePerson
列表(假设列表按字母顺序排序)
谢谢!
答案 0 :(得分:6)
更新回答:
如果我们不允许使用为我们完成所有工作的RemoveAll
或LINQ函数,这是一种“手动”更多的方式:
List<Person> newPersons = new List<Person>();
foreach (Person person in persons)
{
if (person.FirstName != "David")
newPersons.Add(person);
}
persons = newPersons();
.NET中新列表的构建速度非常快。逐个删除项目很慢,因为首先必须在列表中找到要删除的每个元素,然后在删除它时,必须向上移动列表的其余部分以填补空白。这比我上面给出的方法要慢得多。
为了使删除操作更快,列表可以按排序顺序保存或按名字分组。但是最初创建列表的速度会慢一些。
旧答案:
您似乎对简洁的解决方案感兴趣,而不是对具有最佳性能的解决方案感兴趣。如果您使用的是.NET 3.5,则可以使用:
persons = persons.Where(person => person.FirstName != "David").ToList();
哦,List有一个RemoveAll方法:
names.RemoveAll(person => person.FirstName == "David");
(注意Jimmy在我做之前发布了RemoveAll
的想法。)
答案 1 :(得分:3)
要获得简洁的方法,请使用RemoveAll。
list.RemoveAll(person => person.FirstName == "David")
对于(可能?我没有运行任何基准)基于列表中的顺序的有效方法,使用List.RemoveRange - 但你必须找到索引。
class NameComparer : IComparer<Name>
{
public int Compare(Name x, Name y) {
return x.First.CompareTo(y.First);
}
}
...
...
var comparer = new NameComparer();
var david = new Name { First = "David" };
int guess = list.BinarySearch(david, comparer);
int start, end;
start = list.FindLastIndex(guess, person => person.First != "David") + 1;
if (start > 0 && list[start].First == "David") {
end = list.FindIndex(guess, person => person.First != "David");
list.RemoveRange(start, end - start);
}