I am working with C# and I have a dictionary called intervalRecordsPerObject
of type Dictionary<string, List<TimeInterval>>
. I need to iterate through the dictionary. The problem is: everytime I iterate through the dictionary, more KeyValuePairs
may get added to it. As the dictionary grows, I need to keep iterating over the new entries too.
Firstly, I did this: A simple foreach
loop that gave me an InvalidOperationException
saying
Collection was modified; enumeration operation may not execute.
I know I cannot iterate over the Dictionary this way if it keeps changing as C# converts it with ToList()
before foreach
loop.
I know I can copy the keys to a temporary array, iterate over the dictionary using simple for
loop and Count
and whenever a new entry is added to the dictionary, add the corresponding key to the array too. Now, the problem is a simple array cannot grow dynamically and I don't know beforehand what the required size could be.
To move ahead, I thought I'd do this:
List<string> keyList = new List<string>(intervalRecordsPerObject.Count);
intervalRecordsPerObject.Keys.CopyTo(keyList.ToArray(), 0);
I cannot do this either. keyList
is currently empty and therefore keyList.toArray()
returns an array of length 0 which gives me an ArgumentException
saying
Destination array is not long enough to copy all the items in the collection. Check array index and length.
I am stuck! Any idea what more can I try? Thanks for any help.
The dictionary stores the time intervals for which a particular object is present. Key is the ID of the object. New entries may get added in every iteration (worst case) or may not get added even once. Whether or not entries are added is decided by a few conditions (whether the object overlaps with some other intervals, etc.). This triggers a change in the ID and the corresponding interval list which is then added as a new entry to the dictionary.
Something like this:
List<string> keys = dict.Keys.ToList();
for (int i = 0; i < keys.Count; i++)
{
var key = keys[i];
List<TimeInterval> value;
if (!dict.TryGetValue(key, out value))
{
continue;
}
dict.Add("NewKey", yourValue);
keys.Add("NewKey");
}
The trick here is that you enumerate the List<T>
by index ! In this way, even if you add new elements, the for (...)
will "catch" them.
Other possible solution, by using a temporary Dictionary<,>
:
// The main dictionary
var dict = new Dictionary<string, List<TimeInterval>>();
// The temporary dictionary where new keys are added
var next = new Dictionary<string, List<TimeInterval>>();
// current will contain dict or the various instances of next
// (multiple new Dictionary<string, List<TimeInterval>>(); can
// be created)
var current = dict;
while (true)
{
foreach (var kv in current)
{
// if necessary
List<TimeInterval> value = null;
// We add items only to next, that will be processed
// in the next while (true) cycle
next.Add("NewKey", value);
}
if (next.Count == 0)
{
// Nothing was added in this cycle, we have finished
break;
}
foreach (var kv in next)
{
dict.Add(kv.Key, kv.Value);
}
current = next;
next = new Dictionary<string, List<TimeInterval>>();
}
You can access the Keys
by positions rather than by content and use a normal For loop
(allowing additions/removals without any restriction).
for (int i = 0; i < dict.Keys.Count; i++)
{
string curKey = dict.Keys.ElementAt(i);
TimeInterval curVal = dict.Values.ElementAt(i);
//TimeInterval curVal = dict[curKey];
//Can add or remove entries
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.