Удалить объект из общего списка по ID
у меня есть домен класс, как это:
public class DomainClass
{
public virtual string name{get;set;}
public virtual IList<Note> Notes{get;set;}
}
как я могу удалить элемент из IList<Note>
? Я мог бы сделать это, если бы это был список, но он должен быть IList
поскольку я использую Nhibernate для моего слоя persistance.
в идеале я хотел подобный метод в моем классе домена:
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 ответов
вы можете отфильтровать элементы, которые вы не хотите, и создать новый список только с элементами, которые вы хотите:
public virtual void RemoveNote(int id)
{
//remove the note from the list here
Notes = Notes.Where(note => note.Id != id).ToList();
}
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
.
Edit: спасибо Магнусу и rsbarro за то, что показали мою ошибку.
Если вы можете изменить структуру данных, я бы предложил использовать 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>>
вместо.
можно код вручную. Наивная реализация-O (n*k) с n количеством элементов в списке и k количеством элементов, которые вы хотите удалить. Если вы хотите просто удалить один элемент это быстро.
но если вы хотите удалить много элементов, то собственная реализация становится O(n^2)
много IList<T>
реализаций(в том числе List<T>
, не знаю, как ведет себя список NHibernate), и вам нужно написать немного больше кода, чтобы получить O(n)
RemoveAll
реализация.
одна возможная реализация из старого ответа:список, не потерять ссылку
трюк с этой реализацией заключается в том, что In перемещает сохраненные элементы в начало списка в O(n). Затем он продолжает удалять последний элемент списка(который обычно равен O(1), так как нет необходимости перемещать элементы), поэтому усечение становится o (n) total. Это означает, что весь алгоритм равен O (n).
пожалуйста, учтите, что в некоторых случаях лучше избегать общественные виртуалов используйте метод шаблона шаблон таким образом:
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)
{
}
вы можете получить массив элементов для удаления. Чем удалить их из списка в цикле. Посмотрите на этот образец:
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);
}