Ahe*_*eho 180 .net c# .net-2.0
我正在尝试从字典中构建饼图.在我显示饼图之前,我想整理数据.我正在删除任何小于饼的5%的饼图,并将它们放入"其他"饼图中.但是我Collection was modified; enumeration operation may not execute
在运行时遇到异常.
我理解为什么你不能在迭代它们时添加或删除字典中的项目.但是我不明白为什么你不能简单地改变foreach循环中现有键的值.
任何建议:修复我的代码,将不胜感激.
Dictionary<string, int> colStates = new Dictionary<string,int>();
// ...
// Some code to populate colStates dictionary
// ...
int OtherCount = 0;
foreach(string key in colStates.Keys)
{
double Percent = colStates[key] / TotalCount;
if (Percent < 0.05)
{
OtherCount += colStates[key];
colStates[key] = 0;
}
}
colStates.Add("Other", OtherCount);
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 248
在字典中设置值会更新其内部"版本号" - 使迭代器无效,以及与键或值集合关联的任何迭代器.
我确实看到了你的观点,但与此同时,如果值集合可能在迭代中发生变化,那将会很奇怪 - 为简单起见,只有一个版本号.
修复此类事情的常规方法是先预先复制密钥集合并迭代副本,或者迭代原始集合,但保留一系列更改,您将在完成迭代后应用这些更改.
例如:
首先复制密钥
List<string> keys = new List<string>(colStates.Keys);
foreach(string key in keys)
{
double percent = colStates[key] / TotalCount;
if (percent < 0.05)
{
OtherCount += colStates[key];
colStates[key] = 0;
}
}
Run Code Online (Sandbox Code Playgroud)
要么...
创建修改列表
List<string> keysToNuke = new List<string>();
foreach(string key in colStates.Keys)
{
double percent = colStates[key] / TotalCount;
if (percent < 0.05)
{
OtherCount += colStates[key];
keysToNuke.Add(key);
}
}
foreach (string key in keysToNuke)
{
colStates[key] = 0;
}
Run Code Online (Sandbox Code Playgroud)
小智 68
ToList()
在foreach
循环中调用.这样我们就不需要临时变量副本了.这取决于自.Net 3.5以来可用的Linq.
using System.Linq;
foreach(string key in colStates.Keys.ToList())
{
double Percent = colStates[key] / TotalCount;
if (Percent < 0.05)
{
OtherCount += colStates[key];
colStates[key] = 0;
}
}
Run Code Online (Sandbox Code Playgroud)
Cod*_*ile 20
您正在修改此行中的集合:
colStates [key] = 0;
通过这样做,你实际上是删除并重新插入一些东西(就IEnumerable而言,无论如何都是这样).
如果你编辑你正在存储的值的成员,那就没问题,但是你正在编辑值本身,IEnumberable不喜欢这样.
我使用的解决方案是消除foreach循环并只使用for循环.简单的for循环不会检查您知道不会影响集合的更改.
这是你如何做到的:
List<string> keys = new List<string>(colStates.Keys);
for(int i = 0; i < keys.Count; i++)
{
string key = keys[i];
double Percent = colStates[key] / TotalCount;
if (Percent < 0.05)
{
OtherCount += colStates[key];
colStates[key] = 0;
}
}
Run Code Online (Sandbox Code Playgroud)
在 .NET 5 中,枚举字典时可以更改字典项。
Pull 请求是:允许 Dictionary 在枚举期间覆盖,问题是考虑从 Dictionary<TKey, TValue> 的覆盖中删除 _version++。
现在你可以:
foreach (var pair in dict)
dict[pair.Key] = pair.Value + 1;
Run Code Online (Sandbox Code Playgroud)
您不能直接在ForEach中修改键或值,但可以修改其成员。例如,这应该工作:
public class State {
public int Value;
}
...
Dictionary<string, State> colStates = new Dictionary<string,State>();
int OtherCount = 0;
foreach(string key in colStates.Keys)
{
double Percent = colStates[key].Value / TotalCount;
if (Percent < 0.05)
{
OtherCount += colStates[key].Value;
colStates[key].Value = 0;
}
}
colStates.Add("Other", new State { Value = OtherCount } );
Run Code Online (Sandbox Code Playgroud)