Spring4D无法对有序字典进行排序
Spring4D cannot sort an ordered dictionary
我需要一本可以排序的字典。我认为 Spring4D TOrderedDictionary 是一个 class 实现但我无法使其工作:排序不起作用。
我构建了一个小测试程序来显示我遇到的问题:
program Spring4DOrderedDictionaryTest;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Generics.Collections,
System.Generics.Defaults,
Spring.Collections;
type
TKey = TPair<Double, Integer>;
TValue = Integer;
TEqComparer = class(TEqualityComparer<TKey>, IEqualityComparer<TKey>)
function Equals(const Left, Right: TKey): Boolean; reintroduce;
function GetHashCode(const Value: TKey): Integer; reintroduce;
end;
TAComparer = class(TComparer<TPair<TPair<Double, Integer>, Integer>>, IComparer<TPair<TKey, TValue>>)
function Compare(const Left, Right: TPair<TKey, Integer>): Integer; override;
end;
function TEqComparer.Equals(const Left, Right: TKey): Boolean;
begin
Result := Abs(Left.Key - Right.Key) < 1E-9;
if Result then
Result := Left.Value = Right.Value;
end;
function TEqComparer.GetHashCode(const Value: TKey): Integer;
begin
Result := Round(Value.Key * 1E6) + Value.Value;
end;
function TAComparer.Compare(const Left, Right: TPair<TKey, Integer>): Integer;
begin
if Abs(Left.Key.Key - Right.Key.Key) < 1E-9 then begin
if Left.Key.Value < Right.Key.Value then
Result := -1
else if Left.Key.Value > Right.Key.Value then
Result := 1
else
Result := 0;
end
else begin
if Left.Key.Key < Right.Key.Key then
Result := -1
else if Left.Key.Key > Right.Key.Key then
Result := 1
else
Result := 0;
end;
end;
const
SEG_START = 0;
SEG_END = 1;
var
Events : IOrderedDictionary<TKey, TValue>;
Event : TPair<TKey, TValue>;
EqComparer : IEqualityComparer<TKey>;
AComparer : IComparer<TPair<TKey, TValue>>;
begin
EqComparer := TEqComparer.Create;
AComparer := TAComparer.Create;
Events := TCollections.CreateOrderedDictionary<TKey, TValue>;//(EqComparer);
// Put some data into the dictionary
Events.Add(TKey.Create(-7.41, SEG_START), 0);
Events.Add(TKey.Create(-1.3, SEG_END ), 0);
Events.Add(TKey.Create(-4.0, SEG_START), 1);
Events.Add(TKey.Create(-4.21, SEG_END ), 1);
Events.Add(TKey.Create(-4.92, SEG_START), 2);
Events.Add(TKey.Create(-4.26, SEG_END ), 2);
Events.Add(TKey.Create(-4.55, SEG_START), 3);
Events.Add(TKey.Create(-2.54, SEG_END ), 3);
Events.Add(TKey.Create(-3.70, SEG_START), 4);
Events.Add(TKey.Create(-3.70, SEG_END ), 4);
// Sort the dictionary
Events.Ordered(AComparer);
// Show the values in dictionary (Should be sorted -7.41 first and -1.3 last)
for Event in Events do
WriteLn(Format(' %5.2f %d %d', [Event.Key.Key, Event.Key.Value, Event.Value]));
ReadLn;
end.
上面的代码以添加顺序显示值,而不是 - 我认为 - AComparer 应该创建的顺序。
我尝试使用或不使用相等比较器创建 OrderedDictionary:没有变化。
感谢任何帮助。
首先你必须知道,通常字典中项目的顺序是不确定的,因为它取决于底层数据结构——通常它是一个哈希表,所以项目的顺序虽然确定性的出现“随机”或没有特定的顺序.
现在spring4d中有一些字典可以保证项目的顺序。
在1.2.2(目前最新发布的版本)中,一般有三种创建字典的方式:
TCollections.CreateDictionary // internally is just a wrapper around the TDictionary from System.Generics.Collections
TCollections.CreateSortedDictionary // internally uses a red/black tree which makes items ordered - when not explicitly passed it uses the default comparer for the key type
TCollections.CreateOrderedDictionary // internally uses an additional list to preserve items in order they were added to the dictionary
在即将到来的2.0(目前开发分支)有两种方式:
TCollections.CreateDictionary // internally uses a new implementation based on a hashtable which also preserves the order of addition
TCollections.CreateSortedDictionary // same as in 1.2.2 this uses a red/black tree to store items based on the IComparer<TKey>
其次,您必须知道 Ordered
方法来自 IEnumerable<T>
并且不会修改调用它的集合,而是 returns 一个新的 IEnumerable<T>
表示按您传递给该函数的比较器确定的顺序排列的项目。
所以你有两个选择:
- 使用 TCollections.CreateSortedDictionary 传递
IComparer<TKey>
- 请记住,由于 red/black 树的工作方式,如果您更改之后确定顺序的值,顺序可能会中断。
- 利用
Ordered
结果并迭代
我需要一本可以排序的字典。我认为 Spring4D TOrderedDictionary 是一个 class 实现但我无法使其工作:排序不起作用。
我构建了一个小测试程序来显示我遇到的问题:
program Spring4DOrderedDictionaryTest;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Generics.Collections,
System.Generics.Defaults,
Spring.Collections;
type
TKey = TPair<Double, Integer>;
TValue = Integer;
TEqComparer = class(TEqualityComparer<TKey>, IEqualityComparer<TKey>)
function Equals(const Left, Right: TKey): Boolean; reintroduce;
function GetHashCode(const Value: TKey): Integer; reintroduce;
end;
TAComparer = class(TComparer<TPair<TPair<Double, Integer>, Integer>>, IComparer<TPair<TKey, TValue>>)
function Compare(const Left, Right: TPair<TKey, Integer>): Integer; override;
end;
function TEqComparer.Equals(const Left, Right: TKey): Boolean;
begin
Result := Abs(Left.Key - Right.Key) < 1E-9;
if Result then
Result := Left.Value = Right.Value;
end;
function TEqComparer.GetHashCode(const Value: TKey): Integer;
begin
Result := Round(Value.Key * 1E6) + Value.Value;
end;
function TAComparer.Compare(const Left, Right: TPair<TKey, Integer>): Integer;
begin
if Abs(Left.Key.Key - Right.Key.Key) < 1E-9 then begin
if Left.Key.Value < Right.Key.Value then
Result := -1
else if Left.Key.Value > Right.Key.Value then
Result := 1
else
Result := 0;
end
else begin
if Left.Key.Key < Right.Key.Key then
Result := -1
else if Left.Key.Key > Right.Key.Key then
Result := 1
else
Result := 0;
end;
end;
const
SEG_START = 0;
SEG_END = 1;
var
Events : IOrderedDictionary<TKey, TValue>;
Event : TPair<TKey, TValue>;
EqComparer : IEqualityComparer<TKey>;
AComparer : IComparer<TPair<TKey, TValue>>;
begin
EqComparer := TEqComparer.Create;
AComparer := TAComparer.Create;
Events := TCollections.CreateOrderedDictionary<TKey, TValue>;//(EqComparer);
// Put some data into the dictionary
Events.Add(TKey.Create(-7.41, SEG_START), 0);
Events.Add(TKey.Create(-1.3, SEG_END ), 0);
Events.Add(TKey.Create(-4.0, SEG_START), 1);
Events.Add(TKey.Create(-4.21, SEG_END ), 1);
Events.Add(TKey.Create(-4.92, SEG_START), 2);
Events.Add(TKey.Create(-4.26, SEG_END ), 2);
Events.Add(TKey.Create(-4.55, SEG_START), 3);
Events.Add(TKey.Create(-2.54, SEG_END ), 3);
Events.Add(TKey.Create(-3.70, SEG_START), 4);
Events.Add(TKey.Create(-3.70, SEG_END ), 4);
// Sort the dictionary
Events.Ordered(AComparer);
// Show the values in dictionary (Should be sorted -7.41 first and -1.3 last)
for Event in Events do
WriteLn(Format(' %5.2f %d %d', [Event.Key.Key, Event.Key.Value, Event.Value]));
ReadLn;
end.
上面的代码以添加顺序显示值,而不是 - 我认为 - AComparer 应该创建的顺序。
我尝试使用或不使用相等比较器创建 OrderedDictionary:没有变化。
感谢任何帮助。
首先你必须知道,通常字典中项目的顺序是不确定的,因为它取决于底层数据结构——通常它是一个哈希表,所以项目的顺序虽然确定性的出现“随机”或没有特定的顺序.
现在spring4d中有一些字典可以保证项目的顺序。
在1.2.2(目前最新发布的版本)中,一般有三种创建字典的方式:
TCollections.CreateDictionary // internally is just a wrapper around the TDictionary from System.Generics.Collections
TCollections.CreateSortedDictionary // internally uses a red/black tree which makes items ordered - when not explicitly passed it uses the default comparer for the key type
TCollections.CreateOrderedDictionary // internally uses an additional list to preserve items in order they were added to the dictionary
在即将到来的2.0(目前开发分支)有两种方式:
TCollections.CreateDictionary // internally uses a new implementation based on a hashtable which also preserves the order of addition
TCollections.CreateSortedDictionary // same as in 1.2.2 this uses a red/black tree to store items based on the IComparer<TKey>
其次,您必须知道 Ordered
方法来自 IEnumerable<T>
并且不会修改调用它的集合,而是 returns 一个新的 IEnumerable<T>
表示按您传递给该函数的比较器确定的顺序排列的项目。
所以你有两个选择:
- 使用 TCollections.CreateSortedDictionary 传递
IComparer<TKey>
- 请记住,由于 red/black 树的工作方式,如果您更改之后确定顺序的值,顺序可能会中断。 - 利用
Ordered
结果并迭代