Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to iterate a TDictionary and delete item?

Tags:

delphi-xe2

I have a TDictionary and add some items to it:

for index := 0 to 10 do
   dict.Add(IntToStr(index), index);

Now, I need to iterate the container and remove items I wanted:

pairEnum := dict.GetEnumerator;
while pairEnum.MoveNext do
begin
  if pairEnum.Current.Value mod 2 = 0 then
     dict.Remove(pairEunm.Current.Key);
end;

I expect I now only have odd number in the dictionary. But what I actually got are:

key=1 value=1
key=3 value=3
key=5 value=5
key=7 value=7
key=9 value=9
key=8 value=8 <-

Why the "8" wasn't removed from dictionary?

If I add more items. e.g.

for index := 0 to 12 do
   dict.Add(IntToStr(index), index);

Then, the result is correct. Why is that? How can I correctly iterate a TDictionary and remove items? Thanks.

like image 357
trudger Avatar asked Oct 28 '13 04:10

trudger


2 Answers

It is unsafe to remove items while iterating an enumerable. You should keep another list of the keys that you want to remove and start removing them once your iteration is completed.

like image 117
idursun Avatar answered Sep 24 '22 13:09

idursun


You need to iterate through the dictionary in reverse. Unfortunately, Delphi by default does not provide a "For MyObj in dict Reverse" or similar function so you have to do this another way:

for ix := dict.Count - 1 downto 0 do
  if (dict.Keys.ToArray[ix] mod 2) = 0 then
    dict.Remove(dict.Keys.ToArray[ix]);
like image 45
SteveC Avatar answered Sep 21 '22 13:09

SteveC