通过id从通用列表中删除对象

时间:2011-06-25 13:56:14

标签: c# list generics compare

我有这样的域类:

public class DomainClass
{
  public virtual string name{get;set;}
  public virtual IList<Note> Notes{get;set;}
}

如何从IList<Note>删除项目?如果它是List,我可以这样做,但它必须是IList,因为我使用Nhibernate作为我的持久层。

理想情况下,我想在我的域类中使用这样的方法:

public virtual void RemoveNote(int id)
{
   //remove the note from the list here

   List<Note> notes = (List<Note>)Notes

   notes.RemoveAll(delegate (Note note)
   {
       return (note.Id = id)
   });
}

但我无法将IList强制转换为List。这周围有更优雅的方式吗?

6 个答案:

答案 0 :(得分:29)

您可以过滤掉您不想要的项目,并创建一个只包含您想要的项目的新列表:

public virtual void RemoveNote(int id)
{
   //remove the note from the list here

   Notes = Notes.Where(note => note.Id != id).ToList();
}

答案 1 :(得分:10)

Edit2:此方法不需要转换为 List

foreach (var n in Notes.Where(note => note.Id == id).ToArray()) Notes.Remove(n);

...或

Notes.Remove(Notes.Where(note => note.Id == id).First());

第一个是最好的 如果没有id的注释,则第二个将抛出异常。

编辑:感谢Magnus和rsbarro显示我的错误。

答案 2 :(得分:2)

您可以手动编码。天真的实现是O(n * k),其中n是列表中的项目数,k是要删除的项目数。如果你想删除一个项目,那就快了。

但是如果你想删除很多项,那么对于许多O(n^2)实现(包括IList<T>,原生实现变为List<T>,不知道NHibernate的列表是如何表现的)你需要写一个需要更多代码才能获得O(n) RemoveAll实现。

旧答案中的一种可能的实施方式:List, not lose the reference

这种实现的技巧是将保留的项目移动到O(n)中列表的开头。然后它继续删除列表的最后一项(通常为O(1),因为没有元素需要移动),因此截断变为O(n)总计。这意味着整个算法是O(n)。

答案 3 :(得分:2)

如果您可以更改数据结构,我建议使用Dictionary。你可以选择:

public class DomainClass
{
  public virtual string name{get;set;}
  public virtual IDictionary<int, Note> Notes {get; set;}

  //Helper property to get the notes in the dictionary
  public IEnumerable<Note> AllNotes
  {
    get
    {
      return notes.Select (n => n.Value);
    }
  }

  public virtual void RemoveNote(int id)
  {
     Notes.Remove(id);
  }

}

如果ID不是唯一的,请改用IDictionary<int, IList<Note>>

答案 4 :(得分:1)

请考虑,在某些情况下,最好避免公共虚拟,请以这种方式使用template method模式:

 public void Load(IExecutionContext context) 
 { 
      // Can safely set properties, call methods, add events, etc...
      this.Load(context);            
      // Can safely set properties, call methods, add events, etc. 
 }

 protected virtual void Load(IExecutionContext context) 
 {
 }

答案 5 :(得分:0)

您可以收到一系列要删除的项目。然后将它们从循环列表中删除。 看看这个样本:

IList<int> list = new List<int> { 1, 2, 3, 4, 5, 1, 3, 5 };

var valuesToRemove = list.Where(i => i == 1).ToArray();

foreach (var item in valuesToRemove)
{
    list.Remove(item);
}