我在一个名为current的变量中有一个巨大的空白值字典,如下所示:
struct movieuser {blah blah blah}
Dictionary<movieuser, float> questions = new Dictionary<movieuser, float>();
所以我循环阅读这本词典并需要填写“答案”,如下所示:
for(var k = questions.Keys.GetEnumerator();k.MoveNext(); )
{
questions[k.Current] = retrieveGuess(k.Current.userID, k.Current.movieID);
}
现在,这不起作用,因为我尝试修改我循环的字典时遇到InvalidOperationException。但是,您可以看到代码应该可以正常工作 - 因为我没有添加或删除任何值,只是修改了值。但是,我理解为什么它害怕我尝试这个。
这样做的首选方式是什么?我无法想出一种在没有使用迭代器的情况下遍历字典的方法。
我真的不想创建整个数组的副本,因为它是很多数据并且会像我的感恩节一样吃掉我的ram。
谢谢, 戴夫
答案 0 :(得分:2)
是否有任何理由不能同时使用键和值填充字典?
foreach(var key in someListOfKeys)
{
questions.Add(key, retrieveGuess(key.userID, key.movieID);
}
答案 1 :(得分:2)
马特的回答,首先获得钥匙,分开是正确的方法。是的,会有一些冗余 - 但它会起作用。我将采用一个易于调试和维护的工作程序而不是一个有效的程序,这个程序要么无法工作,要么难以维护。
不要忘记,如果你使MovieUser
成为引用类型,那么数组只会是你拥有用户的引用数量 - 这个数量非常小。一百万用户在x64上只占用4MB或8MB。你有多少用户?
因此,您的代码应该是:
IEnumerable<MovieUser> users = RetrieveUsers();
IDictionary<MovieUser, float> questions = new Dictionary<MovieUser, float>();
foreach (MovieUser user in users)
{
questions[user] = RetrieveGuess(user);
}
如果你使用的是.NET 3.5(因此可以使用LINQ),那就更容易了:
IDictionary<MovieUser, float> questions =
RetrieveUsers.ToDictionary(user => user, user => RetrieveGuess(user));
请注意,如果RetrieveUsers()
可以从其来源(例如文件)中流式传输用户列表,那么无论如何它都会很有效率,因为您一次都不需要知道多个用户。重新填充字典。
对其余代码的一些评论:
Dispose
的{{1}}上致电IEnumerator<T>
。如果您只使用GetEnumerator
,您的代码将更简单并且更安全。foreach
几乎肯定是一个班级。你有把它变成结构的真正理由吗?答案 2 :(得分:0)
将字典键存储在临时集合中,然后遍历临时集合并使用键值作为索引器参数。这应该可以解决这个问题。