gpt4 book ai didi

delphi - 使用 TDictionary "for...in"

转载 作者:行者123 更新时间:2023-12-02 19:41:55 29 4
gpt4 key购买 nike

我正在使用 Delphi Berlin 10.1(最新更新),并且我的应用程序中的 TDictionary 遇到一些特定值的问题。 “for..in”无法正确循环。

下面是一个示例代码,其中“for...in”不循环遍历所有值,另一个示例则循环遍历所有值。

在第一种情况下,“for...in”循环仅执行两个步骤,而在第二种情况下,它会执行所有步骤。

procedure TForm1.btn1Click(Sender: TObject);
var
tmpPar: TPair<Integer, Integer>;
tmpDictionary: TDictionary<Integer, Integer>;
begin
// NOT WORKING
tmpDictionary := TDictionary<Integer, Integer>.Create;
try
tmpDictionary.Add(631, 40832);
tmpDictionary.Add(1312, 40837);
tmpDictionary.Add(5947, 40842);

for tmpPar in tmpDictionary do
begin
tmpDictionary.Remove(tmpPar.Key);
end;
finally
tmpDictionary.Free;
end;

// WORKING
tmpDictionary := TDictionary<Integer, Integer>.Create;
try
tmpDictionary.Add(123, 5432);
tmpDictionary.Add(453, 23);
tmpDictionary.Add(76, 2334);

for tmpPar in tmpDictionary do
begin
tmpDictionary.Remove(tmpPar.Key);
end;
finally
tmpDictionary.Free;
end;
end;

第一种情况有问题吗?

提前致谢!

最佳答案

你的例子只是运气好而已 - 不应该期望这个构造会表现良好。如果您单步执行示例,您会发现第一种情况在删除时调用列表重新排序,但第二个示例则不会。

要了解发生了什么,请检查从字典中删除项目的代码:

function TDictionary<TKey,TValue>.DoRemove(const Key: TKey; HashCode: Integer;
Notification: TCollectionNotification): TValue;
var
gap, index, hc, bucket: Integer;
LKey: TKey;
begin
index := GetBucketIndex(Key, HashCode);
if index < 0 then
Exit(Default(TValue));

// Removing item from linear probe hash table is moderately
// tricky. We need to fill in gaps, which will involve moving items
// which may not even hash to the same location.
// Knuth covers it well enough in Vol III. 6.4.; but beware, Algorithm R
// (2nd ed) has a bug: step R4 should go to step R1, not R2 (already errata'd).
// My version does linear probing forward, not backward, however.

// gap refers to the hole that needs filling-in by shifting items down.
// index searches for items that have been probed out of their slot,
// but being careful not to move items if their bucket is between
// our gap and our index (so that they'd be moved before their bucket).
// We move the item at index into the gap, whereupon the new gap is
// at the index. If the index hits a hole, then we're done.

// If our load factor was exactly 1, we'll need to hit this hole
// in order to terminate. Shouldn't normally be necessary, though.
{... etc ...}

您会看到,实现了一种算法,该算法决定在删除项目时何时以及如何对基础列表进行重新排序(这是为了尝试优化已分配内存块中间隙的位置以优化将来的插入)。枚举只是在基础列表中的索引中移动,因此一旦您从列表中删除一个项目,枚举器就不再有效,因为它只会将您移动到基础列表中的下一个索引,该索引已更改。

对于普通列表,删除时通常会反向迭代。但是,对于字典,您必须首先构建要在第一次枚举过程中删除的键列表,然后枚举列表以将它们从字典中删除。

关于delphi - 使用 TDictionary "for...in",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46797980/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com