如何使用TEnumerator按键的顺序遍历TDictionary?
我有这样的东西:
var
Dic: TDictionary<string, string>;
Enum: TPair<string, string>;
begin
Dic := TDictionary<string, string>.create;
Dic.Add('Tired', 'I have been working on this too long');
Dic.Add('Early', 'It is too early in the morning to be working on this');
Dic.Add('HelpMe', 'I need some help');
Dic.Add('Dumb', 'Yes I know this example is dumb');
{ I want to do the following but do it in sorted order by Enum.Key }
for Enum in Dic do
some processing with Enum.Key and Enum.Value;
Dic.Free;
end;
所以我想按顺序处理我的字典:哑巴,早,HelpMe,累。
不幸的是,Delphi在描述枚举器和TEnumerator的具体工作方式方面非常有限,并且没有给出我能找到的示例。web上也很少有关于在Delphi中使用泛型枚举器的文章。
而且上面的示例代码甚至不使用TEnumerator,所以我不知道这些代码是如何设计来使用的。
谢谢巴里你的回答。
自从我提出这个问题以来,我就开始尝试泛化,这是很有趣的。我想开始在我的代码中实现它们。“排序”问题有点令人费解,因为看起来Generics似乎有处理排序的方法,但是对于如何进行排序却没有很好的示例或文档。
最后,我按照巴里的建议,在字典中建立了一个外部索引。尽管如此,感觉还是不太对劲。
然而,后来我有了另一个惊喜:我试图用泛型的加布尔's TDictionary替换GPStringHash。代码在泛型中略显简洁。但底线是TDictionary比Gabr的慢3倍多。对TryGetValue的1704 667次调用需要.45秒,但对TryGetValue例程的相同操作需要.12秒。我不知道为什么,但它可能就像Gabr具有更快的Hash函数和桶形组合一样简单。或者,可能泛型必须针对每一种情况进行泛化,这从本质上减缓了它的速度。
也许Barry或其他Delphi开发人员应该考虑这一点,因为3倍的加速可能最终对每个人都有好处。如果有选择的话,我个人更愿意使用语言中内置的东西,而不是第三方包(即使是像Gabr那样好的包)。但就目前而言,我将坚持GPStringHash。
发布于 2013-04-11 07:23:46
在我的例子中,我使用了>.TKeyCollection类TDictionary < String。
function compareKey(const L, R: String): Integer;
begin
Result := SysUtils.CompareText(L, R);
end;
function getReverseSortedKeyArray(dictionary: TDictionary<String, String): TArray<String>;
var
keyArray: TArray<String>;
keyCollection: TDictionary<String, String>.TKeyCollection;
begin
keyCollection:= TDictionary<String, String>.TKeyCollection.Create(dictionary);
try
keyArray:= keyCollection.ToArray;
TArray.Sort<String>(keyArray, TComparer<String>.Construct(compareKey));
finally
keyCollection.Free;
end;
Result := keyArray;
end;
使用实例:
var
key: String;
keyArray : TArray<String>;
begin
keyArray := getSortedKeyArray (dictionary);
for key in keyArray do
begin
// ...
end;
end;
发布于 2010-03-27 06:43:18
字典是一个哈希表,所以它不按排序顺序存储项。TEnumerator很简单--它只是迭代项的一种方法。
要获得订单中的项目,您需要对它们进行排序。一种方法是将它们放入列表并对列表进行排序,如下所示:
var
list: TList<string>;
begin
list := TList<string>.Create(Dic.Keys);
try
list.Sort;
// process sorted list of items now
finally
list.Free;
end;
end;
发布于 2013-04-18 09:42:22
下面是通过Array<T>
或TList<T>
进行排序的示例代码。它保留了键值对关系,也可以根据值而不是键对进行排序。此外,它使用匿名方法进行排序。
确保在您的Generics.Collections
子句中包括Generics.Defaults
和uses
。使用TArray<T>
进行排序的第一个方法
procedure TestSortDictionaryViaArray;
var
D: TDictionary<string, Integer>;
A: TArray<TPair<string, Integer>>;
P: TPair<string, Integer>;
begin
D := TDictionary<string, Integer>.Create;
D.Add('Test - 6', 6);
D.Add('Test - 1', 1);
D.Add('Test - 0', 0);
D.Add('Test - 4', 4);
D.Add('Test - 3', 3);
D.Add('Test - 5', 0);
D.Add('Test - 2', 2);
A := D.ToArray;
TArray.Sort<TPair<string, Integer>>(A,
TComparer<TPair<string, Integer>>.Construct(
function (const L, R: TPair<string, Integer>): Integer
begin
Result := CompareStr(L.Key, R.Key);
end)
);
for P in A do
ShowMessage(P.Key);
D.Free;
end;
这是使用TList<T>
procedure TestSortDictionaryViaList;
var
D: TDictionary<string, Integer>;
L: TList<TPair<string, Integer>>;
P: TPair<string, Integer>;
begin
D := TDictionary<string, Integer>.Create;
D.Add('Test - 6', 6);
D.Add('Test - 1', 1);
D.Add('Test - 0', 0);
D.Add('Test - 4', 4);
D.Add('Test - 3', 3);
D.Add('Test - 5', 0);
D.Add('Test - 2', 2);
L := TList<TPair<string, Integer>>.Create(D);
L.Sort(
TComparer<TPair<string, Integer>>.Construct(
function (const L, R: TPair<string, Integer>): Integer
begin
Result := CompareStr(L.Key, R.Key);
end)
);
for P in L do
ShowMessage(P.Key);
D.Free;
L.Free;
end;
附加(和不必要的)信息:TList<T>
方法需要释放列表,而TArray<T>
不需要释放。在内部,TList<T>
使用TArray<T>
(例如,TArray
有一个BinarySearch()
类方法,TList<T>
有一个BinarySearch方法)。
https://stackoverflow.com/questions/2528265
复制相似问题