首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Enumerable.ElementAt与foreach

Enumerable.ElementAt与foreach
EN

Stack Overflow用户
提问于 2010-10-06 19:06:27
回答 6查看 4.1K关注 0票数 1

我有一个字典,我需要用传入的数据保持更新,在解析传入数据后,我必须检查字典中是否有任何条目没有出现在传入数据中(当解析传入数据时,传入数据是一个列表,我需要将其映射到字典条目)。

为了避免多次循环来删除条目,我为字典计数运行了一个递减的for循环,然后使用ElementAt获取索引的字典键,然后检查条目是否存在于传入数据中,如果不存在,则从列表中删除该条目。我之所以这样做,是因为在字典键上运行foreach循环并从中删除将引发异常,因为字典键集合将被修改。

我想知道这样做会对执行时间有任何影响。我想知道ElementAt操作的顺序是什么。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 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 ),因为组合序列变成了快速选择,而不是快速排序,然后进行迭代。

票数 7
EN

Stack Overflow用户

发布于 2010-10-06 19:43:44

使用“标记然后删除”技巧作为迭代时无法修改集合的变通方法。

代码语言:javascript
复制
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);
票数 3
EN

Stack Overflow用户

发布于 2010-10-06 19:17:00

如上所述,ElementAt()确实使用了枚举器,所以如果您想要最快的索引访问速度,就应该使用数组。当然,这是以固定长度为代价的,但如果数组的大小不是不断变化的,那么Array.Resize()可能是可行的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3871807

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档