这有效,但不仅看起来不好,但看起来效率不高(我还没有评估性能,因为我知道必须有更好的方法来实现这一点)。
public IEnumerable<Observation> AvailableObservations
{
get
{
foreach (var observation in db.Observations)
{
if (Observations.Any(x => x.Id == observation.Id))
{
}
else
{
yield return observation;
}
}
}
}
基本上,我想要列表db.Observations
中的所有内容
(通过EF6从数据库中提取)并删除this.Observations
中当前选中的所有条目,这是ICollection<Observations>
我已经尝试过使用.Except(this.Observations)但是我得认为可能与使用相关的错误除了在IEnumerable的实体上使用ICollection之外。
任何会删除foreach
循环的东西都是一个好的开始。
答案 0 :(得分:2)
你的循环相当于:
return db.Observations.Where(o => !Observations.Any(oo => oo.Id == o.Id));
但这并不比你拥有的更有效。
一种更有效的方法是创建一个ID的HashSet并过滤掉它:
HashSet<int> ids = new HashSet<int>(Observations.Select(o => o.Id));
return db.Observations.Where(o => !ids.Contains(o.Id));
这样,您只需遍历主列表一次,即可创建可在O(1)时间内搜索的HashSet
。
答案 1 :(得分:1)
您可以在此处进行两项优化:
当前的实施具有O(N * M)
复杂度,其中N
是db.Observations
中的项目数,M
是this.Observations
中的项目数。
首先在HashSet
中创建this.Observations
个ID会有什么帮助?
var observationIds = new HashSet<int>(this.Observations.Select(x => x.Id));
这将允许您快速查找ID。
将此与where子句(使用LINQ的Where()
)相结合,以获得有效的查询:
public IEnumerable<Observation> AvailableObservations
{
get
{
var observationIds = new HashSet<int>(this.Observations.Select(x => x.Id));
return db.Observations.Where(x => !observationIds.Contains(x.Id));
}
}