问题:
我有一个wpf DataGrid
,它绑定到自定义模型类中的对象列表。我需要满足以下要求:
我正在寻找类似于this question的东西,但是我很难将列表转换为与Enumerable.Except
方法兼容的东西。
这是一个小例子:
型号:
public class MyModel
{
public MyModel(int mID, string mName, string mScore)
{
ID = mID;
Name = mName;
Score = mScore;
}
public int ID;
public string Name;
public string Score;
}
尝试将空闲ID最低的新模型添加到我的列表中
List<MyModel> list = new List<MyModel>();
list.Add(new MyModel(0, "Rodney", "189"));
list.Add(new MyModel(1, "Janet", "169"));
list.Add(new MyModel(2, "John", "110"));
list.Add(new MyModel(3, "Samantha", "160"));
list.Add(new MyModel(4, "Daniel", "156"));
list.Add(new MyModel(5, "Jack", "89"));
list.RemoveAll(x => x.ID == 1);
var result = Enumerable.Range(list.Min(m => m.ID), list.Count).Except(list).First();
list.Add(new MyModel(result, "Carolyn", "159")); //Should be 1
我可能必须使用某种lambda表达式,就像我在list.Min()
方法中必须使用的那样,但是花了很长时间才能做到这一点。
答案 0 :(得分:2)
问题是您比较两种不同类型的对象。 Enumerable.Range(list.Min(m => m.ID), list.Count)
是0到5之间整数的枚举,当您使用Except(list)
时,列表由MyModel
个对象组成。
您可能要提取ID:
var result = Enumerable.Range(list.Min(m => m.ID), list.Count).Except(list.Select(m => m.ID)).First();
答案 1 :(得分:2)
为什么要编写复杂的代码?您希望数字大于列表中不存在的最低项目
var result = list.Min(m => m.ID);
while (list.Any(m => m.ID == result))
result++;
这可能不是最快的代码,但是至少很清楚。
答案 2 :(得分:0)
要扩展评论者发布的内容,请使用SortedList,您可以使用它来跟踪免费ID。这样,您就不必寻找差距。当您向主列表中添加某些内容时,请从空闲列表中删除第一个整数,并将该值用作模型的ID。从主列表中删除模型后,将其ID添加到空闲列表中。
答案 3 :(得分:0)
我不想每次添加新模型时都在列表中进行迭代
实际上,这意味着您不能使用Min
,Max
和Except
之类的Linq方法,因为它们会在您的后台进行迭代。
您应该记住的另一件事是RemoveAll
还会遍历列表中的所有项目。因此,您需要更改两件事:首先(已经在Fabjan注释和工具包答案中提到过)是跟踪SortedList
中所有已删除的标识符,其次是使用Dictionary<int, MyModel>
通过密钥删除模型,这是O(1)
的复杂度,而不是O(N)
情况下的List
。
您可以使用以下Container
类来封装此逻辑:
public class Container
{
private readonly Dictionary<int, MyModel> items = new Dictionary<int, MyModel>();
private readonly SortedList removedIds = new SortedList();
private int maxId = 0;
public int Add(MyModel model)
{
int id;
if (removedIds.Count > 0)
{
id = (int) removedIds.GetByIndex(0);
removedIds.RemoveAt(0);
}
else
{
id = maxId++;
}
model.ID = id;
items.Add(id, model);
return id;
}
public void RemoveById(int id)
{
if (!items.ContainsKey(id))
throw new ArgumentException(); // or just return
items.Remove(id);
removedIds.Add(id, id);
}
}