Delphi 字典和排序数据

2023-12-10

我的代码是:

procedure TfrmSettings.btnFillDictClick(Sender: TObject);
var
  Dict: TDictionary<string, string>;
  Item: TPair<string, string>;
begin
  Dict := TDictionary<string, string>.Create();

  Dict.Add('Key1', 'Text1');
  Dict.Add('Key2', 'Text2');
  Dict.Add('Key3', 'Text3');
  Dict.Add('Key4', 'Text4');

  for Item in Dict do
  begin
    ShowMessage(Item.Key + ' ' + Item.Value);
  end;    
end;

为什么几乎每次我在 Showmessage 中得到不同的值?
为什么值不按照添加顺序存储?

我是 Delphi 的菜鸟,不知道 Dictionary 是如何工作的。而且我在谷歌上没有找到任何关于这方面的信息。 您能解释一下为什么会这样吗?
有没有办法在不使用 TList 的情况下使用 Dictionary 来对数据进行排序?

Thanks


字典不维护元素的顺序,因为它的内部组织方式为查找表,并且按键的哈希排序。它们针对速度进行了优化,而不是为了保留顺序。

如果您需要维护元素的顺序,则需要对列表而不是字典。 Delphi 不提供开箱即用的功能。您可以使用以下代码来实现简单的配对列表并根据您的需要对其进行自定义。

type
  TPairs<TKey, TValue> = class(TList < TPair < TKey, TValue >> )
  protected
    fKeyComparer: IComparer<TKey>;
    fValueComparer: IComparer<TValue>;
    function GetValue(Key: TKey): TValue;
    procedure SetValue(Key: TKey; const Value: TValue);
    function ComparePair(const Left, Right: TPair<TKey, TValue>): Integer;
  public
    constructor Create; overload;
    procedure Add(const aKey: TKey; const aValue: TValue); overload;
    function IndexOfKey(const aKey: TKey): Integer;
    function ContainsKey(const aKey: TKey): Boolean; inline;
    property Values[Key: TKey]: TValue read GetValue write SetValue;
  end;

constructor TPairs<TKey, TValue>.Create;
begin
  if fKeyComparer = nil then fKeyComparer := TComparer<TKey>.Default;
  if fValueComparer = nil then fValueComparer := TComparer<TValue>.Default;
  inherited Create(TDelegatedComparer <TPair<TKey, TValue>>.Create(ComparePair));
end;

function TPairs<TKey, TValue>.ComparePair(const Left, Right: TPair<TKey, TValue>): Integer;
begin
  Result := fKeyComparer.Compare(Left.Key, Right.Key);
  if Result = 0 then Result := fValueComparer.Compare(Left.Value, Right.Value);
end;

function TPairs<TKey, TValue>.IndexOfKey(const aKey: TKey): Integer;
var
  i: Integer;
begin
  Result := -1;
  for i := 0 to Count - 1 do
    if fKeyComparer.Compare(Items[i].Key, aKey) = 0 then
      begin
        Result := i;
        break;
      end;
end;

function TPairs<TKey, TValue>.ContainsKey(const aKey: TKey): Boolean;
begin
  Result := IndexOfKey(aKey) >= 0;
end;

function TPairs<TKey, TValue>.GetValue(Key: TKey): TValue;
var
  i: Integer;
begin
  i := IndexOfKey(Key);
  if i >= 0 then Result := Items[i].Value
  else Result := default (TValue);
end;

procedure TPairs<TKey, TValue>.SetValue(Key: TKey; const Value: TValue);
var
  i: Integer;
  Pair: TPair<TKey, TValue>;
begin
  i := IndexOfKey(Key);
  if i >= 0 then FItems[i].Value := Value
  else
    begin
      Pair.Create(Key, Value);
      inherited Add(Pair);
    end;
end;

procedure TPairs<TKey, TValue>.Add(const aKey: TKey; const aValue: TValue);
begin
  SetValue(aKey, aValue);
end;

然后您可以像使用字典一样使用它,但元素的顺序将保持不变。

var
  Pairs: TPairs<string, string>;
  Item: TPair<string, string>;
begin
  Pairs := TPairs<string, string>.Create();

  Pairs.Add('Key1', 'Text1');
  Pairs.Add('Key2', 'Text2');
  Pairs.Add('Key3', 'Text3');
  Pairs.Add('Key4', 'Text4');
  Pairs.Add('Key5', 'Text5');

  for Item in Pairs do
    begin
      Memo1.Lines.Add(Item.Key + ' ' + Item.Value);
    end;
end;

SetValue更新较新的 Delphi 版本,其中FItems不可用于TList<T>后代阶级。

procedure TPairs<TKey, TValue>.SetValue(Key: TKey; const Value: TValue);
var
  i: Integer;
  Pair: TPair<TKey, TValue>;
begin
  i := IndexOfKey(Key);
  if i >= 0 then
    begin
      Pair := Items[i];
      Pair.Value := Value;
      Items[i] := Pair;
    end
  else
    begin
      Pair.Create(Key, Value);
      inherited Add(Pair);
    end;
end;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Delphi 字典和排序数据 的相关文章

随机推荐

  • 使用 readxl 包从 URL 读取 Excel 文件

    考虑互联网上的一个文件 像这个一样 注意 https 中的 s https evs nci nih gov ftp1 CDISC SDTM SDTM 20Terminology xls 如何将文件的第2页读入R 以下代码是所需的近似值 但失
  • 链接选择框 jquery php

    i found thisphp mysql jquery 三个链接选择框的插件 这适用于以下方法 选择框一可见 选择任意后optiononload selectbox 2 并选择任意之后option加载最后一个选择框 3 现在我的问题是 选
  • SwiftUI Inspector 消失在项目中

    在我的 Xcode 项目之一中 SwiftUI 检查器将不再显示 Example 当我创建一个新项目时 我有检查员 知道是什么原因造成的吗 我可以重置项目的设置吗 您必须打开 Canvas 才能在编辑器中包含 SwiftUI 上下文菜单项
  • Windows 窗体 DataGridView 中的折叠式

    我需要在 Windows 窗体 DataGridView 中实现某种手风琴效果 当用户选择一行时 该行将展开以显示更多信息 如果可能的话 还显示一些按钮或其他控件 问题是 我完全不知道如何做到这一点 我尝试在网络上搜索 但没有找到任何可以引
  • ImageField image_width 和 image_height 自动填充现有数据库?

    我有一个现有的数据库表ImageField已经有一堆现有的注册表 我想添加image width and image height在我的模型上 但我需要一些东西来自动填充现有的表格 class ItemImage models Model
  • 滚动时粘性导航栏?

    我目前正在为自己构建一个网站 我发现在多个网站上都有这种非常棒的效果 其中导航栏位于图像下方 但当您滚动经过它时 它会粘在顶部 Example 我怎样才能实现这个目标 另外 如何才能达到类似的效果该网站具有类似的导航栏样式 这是 Matth
  • 为什么设置断点可以让我的代码工作?

    我很新C所以我确信我做错了很多事情 但这让我感到困惑 我的代码应该从用户那里获取标题 并在路由目录中创建一个具有该名称的文件夹 仅当我在上面设置断点时它才有效makeFolder 执行 由于某种原因 在我点击之前稍作休息continue让它
  • Perl + POO 和 Mysql 错误

    我刚刚学了 poo 我开始使用 perl 实现了这一点 但我没有得到预期的输出 mysql 有问题吗 还是坏代码 另外 相同的查询在控制台和工作台上运行 并且此模块添加 chmod x module pm usr bin perl use
  • 如何从外部链接导航到 Bootstrap 4 的特定选项卡

    我想从外部页面链接打开 bootstrap 4 的特定选项卡 第 1 页 nav html 我想从这一页转到第二页 a href index html tab 1 tab 1 a a href index html tab 2 tab 2
  • 调整 QWidget 大小时忽略最小尺寸

    有没有办法让 QWidget 及其任何子类 完全忽略其最小大小 我想要的是 QPushButton 在尺寸太小时时被切断 而不是阻止窗口调整大小 默认行为 您可以使用 button setSizePolicy QSizePolicy Ign
  • 使用 selenium python 使用复合类解析 HTML 内容

    我的 GUI 中有一个显示按钮 用于显示连接状态 带有绿色勾号的按钮表示已建立连接 带有红色叉号的按钮表示没有连接 我必须使用我的代码检查状态 我正在解析该特定标题栏类名 容器流体 的内容 由此 我正在解析该显示按钮的显式内容 elem d
  • 如何从 SQLite 数据库中检索用户位置特定范围内的一组位置

    我有一些位置坐标存储在我的SQLite数据库表 我想检索距用户当前位置 1 公里范围内的位置 现在我正在从数据库中获取所有值 并编写了一个方法来检索我范围内的值 这给我带来了巨大的开销 因为我的表可能包含超过 1000 个坐标 所以我正在寻
  • EF 6:另一个复杂类型中的嵌套复杂类型

    假设我有一个名为 car 的实体 我使用复杂类型来定义 引擎 部分 TableName T CAR public sealed class Car IEngine public EngineType EngineType get set C
  • 使用 Angular js 进行应用程序设计

    一直致力于使用 Angular JS 构建一个巨大的应用程序 在同一主题上看到了太多关于如何最好地设计应用程序的问题 但仍然感到困惑 一个基本的应用程序通常有一个 1 登录页面 索引页面 2 主页 带页眉和页脚 身体是partial com
  • 将两个数据框导出为一个 Excel 文件,并在指定位置的 pandas 中包含两张表

    我有两个数据框 如下所示 df1 Date t factor plan plan score 0 2020 02 01 5 NaN 0 1 2020 02 02 23 NaN 0 2 2020 02 03 14 start 0 3 2020
  • Javascript如何获取所选项目的ID

    我正在使用 Web2Py 将值列表发送到我的视图 我的 HTML 是这样的
  • Excel VBA 计算另一张工作表中的公式

    已解决 问题出在我的公式中 我使用 INDIRECT 引用单元格 当工作表不同时 该单元格不起作用 查看答案 我在一张纸上有一个公式 我想要做的是使用另一张纸上的公式 使用 eval 来评估该公式 然而 结果并不如预期 该公式似乎使用工作表
  • 使用 Chrome 查找 JavaScript 内存泄漏

    我创建了一个非常简单的测试用例 它创建一个 Backbone 视图 将处理程序附加到事件 并实例化一个用户定义的类 我相信 通过单击此示例中的 删除 按钮 所有内容都会被清理 并且不会出现内存泄漏 代码的 jsfiddle 在这里 http
  • 使用单例进行单元测试

    我已经使用 Visual Studio Team Edition 测试框架准备了一些自动测试 我希望其中一项测试按照程序中完成的正常方式连接到数据库 string r providerName ConfigurationManager Co
  • Delphi 字典和排序数据

    我的代码是 procedure TfrmSettings btnFillDictClick Sender TObject var Dict TDictionary