lke*_*ler 19 delphi generics delphi-2009 tdictionary
如何使用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;
Run Code Online (Sandbox Code Playgroud)
所以我想按顺序处理我的字典:Dumb,Early,HelpMe,Tired.
不幸的是,Delphi帮助在描述一般的枚举器和TEnumerator如何具体工作方面是非常小的,并没有给出我能找到的例子.关于在Delphi中使用带有泛型的枚举器,网上也很少写.
我上面的示例代码甚至没有使用TEnumerator,所以我很困惑这是如何设计使用.
谢谢巴里,你的回答.
自从我问这个问题以来,我对Generics的冒险很有意思.我想在我的代码中开始实现它们."排序"问题有点令人困惑,因为看起来Generics似乎有处理内置排序的方法,但是没有关于如何做到这一点的好例子或文档.
最后,我做了Barry建议并在Dictionary中构建了一个外部索引.不过,感觉不对.
不过,后来我有另外一个惊喜:我试图更换贾布尔的GPStringHash与通用的TDictionary.泛型的代码有点干净.但最重要的是,TDictionary比Gabr慢3倍.对TryGetValue的1,704,667次调用耗时0.45秒,但对Gabr的例程执行的操作耗时0.12秒.我不知道为什么,但也许它像Gabr一样简单,具有更快的Hash功能和分组组合.或者也许泛型必须针对每个案例进行推广,并且本质上会减慢它的速度.
从来没有,也许Barry或其他Delphi开发人员应该关注这一点,因为3倍的加速可能最终使每个人受益.如果给出选择,我个人会更早地使用内置于语言中的内容而不是第三方软件包(即使是像Gabr一样好的软件包).但是现在,我会坚持使用GPStringHash.
Bar*_*lly 21
字典是哈希表,因此它不按排序顺序存储项目.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;
Run Code Online (Sandbox Code Playgroud)
在我的例子中,我使用TDictionary <String,String>.TKeyCollection类.
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;
Run Code Online (Sandbox Code Playgroud)
使用示例:
var
key: String;
keyArray : TArray<String>;
begin
keyArray := getSortedKeyArray (dictionary);
for key in keyArray do
begin
// ...
end;
end;
Run Code Online (Sandbox Code Playgroud)
这是对 viaArray<T>
或 a 进行排序的示例代码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;
Run Code Online (Sandbox Code Playgroud)
这是使用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;
Run Code Online (Sandbox Code Playgroud)
附加(和不必要的)信息:该TList<T>
方法需要释放列表,TArray<T>
而不需要释放。在内部,TList<T>
使用TArray<T>
(例如,TArray
有一个BinarySearch()
类方法,并TList<T>
有一个 BinarySearch 方法)。