在 delphi 中具有索引访问的 TDictionary
TDictionary with index access in delphi
我需要一个可以通过键或索引访问的列表。 Delphi XE 中是否有任何对象已经为我处理了这个?
我正在尝试使用 TDictionary
,但没有按索引访问。
我没有得到相同的顺序,使用 ToArray,例如:
procedure TForm1.Button1Click(Sender: TObject);
var list: TDictionary<string, string>;
arr: TArray<string>;
b,a: Integer;
value: string;
begin
list := TDictionary<string, string>.Create();
for a:=0 to 10 do
begin
b:=random(1000);
value := 'index: ' + inttostr(a) + ' - value: ' + inttostr(b);
list.Add(inttostr(b), value);
memo1.Lines.Add(value);
end;
arr := list.Values.ToArray();
for value in arr do
begin
memo2.Lines.Add(value);
end;
end;
结果:
index: 0 - value: 830
index: 1 - value: 265
index: 2 - value: 964
index: 3 - value: 765
index: 4 - value: 917
index: 5 - value: 826
index: 6 - value: 353
index: 7 - value: 431
index: 8 - value: 837
index: 9 - value: 373
index: 10 - value: 805
和
index: 7 - value: 431
index: 8 - value: 837
index: 9 - value: 373
index: 10 - value: 805
index: 4 - value: 917
index: 5 - value: 826
index: 0 - value: 830
index: 2 - value: 964
index: 3 - value: 765
index: 6 - value: 353
index: 1 - value: 265
您可能必须创建自己的 T/IOrderedDictionary
class/interface
界面可能如下所示:
Based on Spring4D - IDictionary/IList
unit OrderedDictionary;
interface
uses
Spring,
Generics.Collections,
Generics.Defaults,
Spring.Collections,
Spring.Collections.Dictionaries,
Spring.Collections.Lists;
type
IOrderedDictionary<K,V> = interface(IDictionary<K,V>)
function Add(const item: TPair<K,V>): Integer;
{$REGION 'Property Accessors'}
function GetCapacity: Integer;
function GetCount: Integer;
function GetItem(index: Integer): TPair<K,V>;
procedure SetCapacity(value: Integer);
procedure SetCount(value: Integer);
procedure SetItem(index: Integer; const item: TPair<K,V>);
{$ENDREGION}
/// <summary>
/// Inserts an item to the IList<TPair<K,V>> at the specified index.
/// </summary>
/// <param name="index">
/// The zero-based index at which item should be inserted.
/// </param>
/// <param name="item">
/// The element to insert into the IList<TPair<K,V>>.
/// </param>
procedure Insert(index: Integer; const item: TPair<K,V>);
procedure InsertRange(index: Integer; const values: array of TPair<K,V>); overload;
procedure InsertRange(index: Integer; const collection: IEnumerable<TPair<K,V>>); overload;
/// <summary>
/// Removes the item at the specified index.
/// </summary>
/// <param name="index">
/// The zero-based index of the item to remove.
/// </param>
/// <exception cref="ArgumentOutOfRangeException">
/// <i>index</i> is not a valid index in the IList<TPair<K,V>>.
/// </exception>
procedure Delete(index: Integer);
procedure DeleteRange(index, count: Integer);
/// <summary>
/// Extracts the item at the specified index.
/// </summary>
/// <param name="index">
/// The zero-based index of the item to extract.
/// </param>
/// <exception cref="ArgumentOutOfRangeException">
/// <i>index</i> is not a valid index in the IList<TPair<K,V>>.
/// </exception>
function ExtractAt(index: Integer): TPair<K,V>;
function ExtractRange(index, count: Integer): TArray<TPair<K,V>>; overload;
/// <summary>
/// Creates a new list that contains a range of the elements in the
/// original list.
/// </summary>
/// <param name="index">
/// The zero-based index at which the range starts.
/// </param>
/// <param name="count">
/// The number of elements in the range.
/// </param>
/// <remarks>
/// If the list contains reference types the elements in the returned
/// list point to the same instance as the elements in the original list.
/// Also if the original list is a <see cref="Spring.Collections.Lists|TObjectList<TPair<K,V>>" />
/// it still owns the objects.
/// </remarks>
function GetRange(index, count: Integer): IList<TPair<K,V>>;
procedure Exchange(index1, index2: Integer);
procedure Move(currentIndex, newIndex: Integer);
procedure Reverse; overload;
procedure Reverse(index, count: Integer); overload;
procedure Sort; overload;
procedure Sort(const comparer: IComparer<K>); overload;
procedure Sort(const comparer: TComparison<K>); overload;
procedure Sort(const comparer: IComparer<K>; index, count: Integer); overload;
procedure Sort(const comparer: TComparison<K>; index, count: Integer); overload;
/// <summary>
/// Determines the index of a specific item in the IList<TPair<K,V>>.
/// </summary>
/// <param name="item">
/// The element to locate in the IList<TPair<K,V>>.
/// </param>
/// <returns>
/// The index of <i>item</i> if found in the list; otherwise, -1.
/// </returns>
/// <remarks>
/// If an element occurs multiple times in the list, the IndexOf method
/// always returns the first instance found.
/// </remarks>
function IndexOf(const Key: K): Integer; overload;
function IndexOf(const Key: K; index: Integer): Integer; overload;
function IndexOf(const Key: K; index, count: Integer): Integer; overload;
function AsList: IList;
/// <summary>
/// Returns the list as read-only list.
/// </summary>
/// <remarks>
/// This method will not perform a copy but will return the same instance
/// as IReadOnlyList<TPair<K,V>>.
/// </remarks>
function AsReadOnlyList: IReadOnlyList<TPair<K,V>>;
procedure TrimExcess;
property Capacity: Integer read GetCapacity write SetCapacity;
property Count: Integer read GetCount write SetCount;
property Items[index: Integer]: TPair<K,V> read GetItem write SetItem; default;
end;
如果您知道(或可以控制)字典如何存储其项目,您可以将 List
设置为 TArray<Integer>
保存字典使用的存储索引号或 TArray<pointer to TPair<K,V>>
.
如果 K
和 V
很小,最好只复制列表。
更好的选择可能是使用 B+Tree 来存储您的项目,在语义上它位于字典和列表之间的某个位置。
我需要一个可以通过键或索引访问的列表。 Delphi XE 中是否有任何对象已经为我处理了这个?
我正在尝试使用 TDictionary
,但没有按索引访问。
我没有得到相同的顺序,使用 ToArray,例如:
procedure TForm1.Button1Click(Sender: TObject);
var list: TDictionary<string, string>;
arr: TArray<string>;
b,a: Integer;
value: string;
begin
list := TDictionary<string, string>.Create();
for a:=0 to 10 do
begin
b:=random(1000);
value := 'index: ' + inttostr(a) + ' - value: ' + inttostr(b);
list.Add(inttostr(b), value);
memo1.Lines.Add(value);
end;
arr := list.Values.ToArray();
for value in arr do
begin
memo2.Lines.Add(value);
end;
end;
结果:
index: 0 - value: 830
index: 1 - value: 265
index: 2 - value: 964
index: 3 - value: 765
index: 4 - value: 917
index: 5 - value: 826
index: 6 - value: 353
index: 7 - value: 431
index: 8 - value: 837
index: 9 - value: 373
index: 10 - value: 805
和
index: 7 - value: 431
index: 8 - value: 837
index: 9 - value: 373
index: 10 - value: 805
index: 4 - value: 917
index: 5 - value: 826
index: 0 - value: 830
index: 2 - value: 964
index: 3 - value: 765
index: 6 - value: 353
index: 1 - value: 265
您可能必须创建自己的 T/IOrderedDictionary
class/interface
界面可能如下所示:
Based on Spring4D - IDictionary/IList
unit OrderedDictionary;
interface
uses
Spring,
Generics.Collections,
Generics.Defaults,
Spring.Collections,
Spring.Collections.Dictionaries,
Spring.Collections.Lists;
type
IOrderedDictionary<K,V> = interface(IDictionary<K,V>)
function Add(const item: TPair<K,V>): Integer;
{$REGION 'Property Accessors'}
function GetCapacity: Integer;
function GetCount: Integer;
function GetItem(index: Integer): TPair<K,V>;
procedure SetCapacity(value: Integer);
procedure SetCount(value: Integer);
procedure SetItem(index: Integer; const item: TPair<K,V>);
{$ENDREGION}
/// <summary>
/// Inserts an item to the IList<TPair<K,V>> at the specified index.
/// </summary>
/// <param name="index">
/// The zero-based index at which item should be inserted.
/// </param>
/// <param name="item">
/// The element to insert into the IList<TPair<K,V>>.
/// </param>
procedure Insert(index: Integer; const item: TPair<K,V>);
procedure InsertRange(index: Integer; const values: array of TPair<K,V>); overload;
procedure InsertRange(index: Integer; const collection: IEnumerable<TPair<K,V>>); overload;
/// <summary>
/// Removes the item at the specified index.
/// </summary>
/// <param name="index">
/// The zero-based index of the item to remove.
/// </param>
/// <exception cref="ArgumentOutOfRangeException">
/// <i>index</i> is not a valid index in the IList<TPair<K,V>>.
/// </exception>
procedure Delete(index: Integer);
procedure DeleteRange(index, count: Integer);
/// <summary>
/// Extracts the item at the specified index.
/// </summary>
/// <param name="index">
/// The zero-based index of the item to extract.
/// </param>
/// <exception cref="ArgumentOutOfRangeException">
/// <i>index</i> is not a valid index in the IList<TPair<K,V>>.
/// </exception>
function ExtractAt(index: Integer): TPair<K,V>;
function ExtractRange(index, count: Integer): TArray<TPair<K,V>>; overload;
/// <summary>
/// Creates a new list that contains a range of the elements in the
/// original list.
/// </summary>
/// <param name="index">
/// The zero-based index at which the range starts.
/// </param>
/// <param name="count">
/// The number of elements in the range.
/// </param>
/// <remarks>
/// If the list contains reference types the elements in the returned
/// list point to the same instance as the elements in the original list.
/// Also if the original list is a <see cref="Spring.Collections.Lists|TObjectList<TPair<K,V>>" />
/// it still owns the objects.
/// </remarks>
function GetRange(index, count: Integer): IList<TPair<K,V>>;
procedure Exchange(index1, index2: Integer);
procedure Move(currentIndex, newIndex: Integer);
procedure Reverse; overload;
procedure Reverse(index, count: Integer); overload;
procedure Sort; overload;
procedure Sort(const comparer: IComparer<K>); overload;
procedure Sort(const comparer: TComparison<K>); overload;
procedure Sort(const comparer: IComparer<K>; index, count: Integer); overload;
procedure Sort(const comparer: TComparison<K>; index, count: Integer); overload;
/// <summary>
/// Determines the index of a specific item in the IList<TPair<K,V>>.
/// </summary>
/// <param name="item">
/// The element to locate in the IList<TPair<K,V>>.
/// </param>
/// <returns>
/// The index of <i>item</i> if found in the list; otherwise, -1.
/// </returns>
/// <remarks>
/// If an element occurs multiple times in the list, the IndexOf method
/// always returns the first instance found.
/// </remarks>
function IndexOf(const Key: K): Integer; overload;
function IndexOf(const Key: K; index: Integer): Integer; overload;
function IndexOf(const Key: K; index, count: Integer): Integer; overload;
function AsList: IList;
/// <summary>
/// Returns the list as read-only list.
/// </summary>
/// <remarks>
/// This method will not perform a copy but will return the same instance
/// as IReadOnlyList<TPair<K,V>>.
/// </remarks>
function AsReadOnlyList: IReadOnlyList<TPair<K,V>>;
procedure TrimExcess;
property Capacity: Integer read GetCapacity write SetCapacity;
property Count: Integer read GetCount write SetCount;
property Items[index: Integer]: TPair<K,V> read GetItem write SetItem; default;
end;
如果您知道(或可以控制)字典如何存储其项目,您可以将 List
设置为 TArray<Integer>
保存字典使用的存储索引号或 TArray<pointer to TPair<K,V>>
.
如果 K
和 V
很小,最好只复制列表。
更好的选择可能是使用 B+Tree 来存储您的项目,在语义上它位于字典和列表之间的某个位置。