为列表编写删除名称循环

时间:2010-03-03 23:40:37

标签: c# algorithm list

我正在尝试制作一个有效的删除方法来处理列表。这种情况如下:

说...我有一个(可能)庞大的名单:

Alex Smith
Anna Hobb
Bertie Blackman
Bill Clinton
David Smith
David Warner
George Jung
George Washington
William Wobbits

让我们说这是List<Person>,其中Person具有属性FirstNameLastName。如示例中所示,两个人可能共享相同的FirstName。我需要做的是查看列表并删除所有Davids,例如。

我正在循环查找所有davids,添加到列表DeletePerson,然后再次循环查看每个DeletePerson并删除。我相信会有更有效的方法吗?效率在这个应用程序中并不重要,但它似乎是一个漫长的方式来做到这一点,我想,因为在第一个名字的字母D后我们知道我们将不再添加到DeletePerson列表(假设列表按字母顺序排序)

谢谢!

2 个答案:

答案 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);
}