Remove object from generic list by id

前提是你 提交于 2019-12-04 16:54:19

问题


I have a domain class like this:

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

How would I go about removing an item from the IList<Note>? I would be able to do it if it was a List but it has to be an IList as I am using Nhibernate for my persistance layer.

Ideally I wanted a method like this in my domain class:

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

But I can't cast the IList as a List. Is there a more elegant way round this?


回答1:


You could filter out the items you don't want and create a new list with only the items you do want:

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

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



回答2:


Edit2: This method doesn't require casting to a List!

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

or...

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

The first one is the best.
The second one will throw an exception if no notes have that id.

Edit: Thanks to Magnus and rsbarro for showing my mistake.




回答3:


If you can change the datastructure I would suggest using a Dictionary. Than you can go with:

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

}

If ID is not unique use IDictionary<int, IList<Note>> instead.




回答4:


You can either code it manually. The naive implementation is O(n*k) with n the number of items in the list, and k the number of items you want to remove. If you want to just remove a single item it is fast.

But if you want to remove many items then the native implementation becomes O(n^2) for many IList<T> implementations(including List<T>, no idea how NHibernate's list behaves) and you need to write a bit more code to get a O(n) RemoveAll implementation.

One possible implementation from an old answer: List, not lose the reference

The trick with this implementation is that in moves the kept items to the beginning of the list in O(n). Then it keeps removing the last item of the list(which is usually O(1) since no elements need to move), so the truncation becomes O(n) total. This means the whole algorithm is O(n).




回答5:


Please consider, that in some cases better to avoid public virtuals, use template method pattern in such a way:

 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) 
 {
 }



回答6:


You can receive an array of items for removing. Than remove them from list in loop. Look at this sample:

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


来源:https://stackoverflow.com/questions/6478175/remove-object-from-generic-list-by-id

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!