How to iterate a TDictionary and delete item?

懵懂的女人 提交于 2020-01-02 03:12:06

问题


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.


回答1:


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.




回答2:


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]);



回答3:


The following form of iteration and deletion within the iteration seems to work.

var
  Item: TPair<string, integer>;

for Item in dict do
begin
  if Item.Value mod 2 = 0 then
    dict.Remove(Item.Key);
end;

This likely works fine because the key and value are being blanked out but the location is not actually being deleted and the iteration does not lose where it is and can continue.



来源:https://stackoverflow.com/questions/19627221/how-to-iterate-a-tdictionary-and-delete-item

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!