我有一个字典,我需要用传入的数据保持更新,在解析传入数据后,我必须检查字典中是否有任何条目没有出现在传入数据中(当解析传入数据时,传入数据是一个列表,我需要将其映射到字典条目)。
为了避免多次循环来删除条目,我为字典计数运行了一个递减的for循环,然后使用ElementAt获取索引的字典键,然后检查条目是否存在于传入数据中,如果不存在,则从列表中删除该条目。我之所以这样做,是因为在字典键上运行foreach循环并从中删除将引发异常,因为字典键集合将被修改。
我想知道这样做会对执行时间有任何影响。我想知道ElementAt操作的顺序是什么。
发布于 2010-10-06 20:05:37
如果您需要提供索引语义,并且不能保证索引语义在基础枚举中可用,则ElementAt非常有用。当所作用的枚举是IList<T> (包括列表和数组)时,它确实使用O(1)索引,但在其他情况下是O( n) *,这使得它在序列中使用,从O(n)操作到O(n *n)。
然而,如果你用dict.Keys.ToList()得到了密钥的副本,那么你可以安全地foreach通过它,因为它不会因为你的字典的变化而改变。
不清楚的是,为什么不用新字典替换旧字典,这样会更快(简单的引用赋值)。
*更新:在linq的.NET核心版本中,ElementAt()为O(1)的情况范围更广,例如在IList<T>上执行Select()的结果。此外,OrderBy(…).ElementAt(…)现在是O(n)而不是O( now ),因为组合序列变成了快速选择,而不是快速排序,然后进行迭代。
发布于 2010-10-06 19:43:44
使用“标记然后删除”技巧作为迭代时无法修改集合的变通方法。
var dict = new Dictionary<int, string>
{
{3, "kuku" },
{1, "zOl"}
};
var newKeys = new List<int> { 1, 2, 4 };
var toRemove = dict.Keys.Except(newKeys).ToList();
foreach (var k in toRemove)
dict.Remove(k);发布于 2010-10-06 19:17:00
如上所述,ElementAt()确实使用了枚举器,所以如果您想要最快的索引访问速度,就应该使用数组。当然,这是以固定长度为代价的,但如果数组的大小不是不断变化的,那么Array.Resize()可能是可行的。
https://stackoverflow.com/questions/3871807
复制相似问题