RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1569590
Accepted
Kromster
Kromster
Asked:2024-03-01 03:42:36 +0000 UTC2024-03-01 03:42:36 +0000 UTC 2024-03-01 03:42:36 +0000 UTC

Delphi 中的哪个标准类允许您双向存储和选择键(字符串)-值(字符串)-索引对?

  • 772

我需要存储键(字符串)-索引(数字)-值(字符串)的组合,以便能够:

  • 有一个索引 - 选择值(很多时候,直接访问是可取的)
  • 有一个索引 - 选择一个键(经常)
  • 有一个键 - 选择一个值(很少)

所有键-键对都是唯一的。索引是单调的(例如从 0 到 10,000)。数据到达时未排序。排序并不重要。

当前的实现 - 2 个对称字典 + 列表:

TKMLibraryKey = string;
TKMLibraryLine = string;

fText: TList<TKMLibraryLine>;
fDictionaryKeyIndex: TDictionary<TKMLibraryKey, Word>;
fDictionaryIndexKey: TDictionary<Word, TKMLibraryKey>;

内存占用 -(V, K + I, I + K) * n

如何才能让这变得更容易呢?也许有某种带有对称对的字典,比如键-键?这样你就可以将自己限制在两个集合中:

fText: TList<TKMLibraryLine>;
TBiDiDictionary<TKMLibraryKey, Word>;

仅基于标准类,无需任何外部库。

delphi
  • 2 2 个回答
  • 45 Views

2 个回答

  • Voted
  1. Alekcvp
    2024-03-01T16:27:25Z2024-03-01T16:27:25Z

    我通过其后继者 TDictionary 看到了它的实现,如下所示:

    type
      PStringPair = ^TStringPair;
      TStringPair = TPair<string, string>;
    
      FIndexedDidctionary = class
      private
        FIndexes: TArray<TStringPair>;
        FKeyPairs: TDictionary<string, string>;
        function GetKeyByIndex(Index: Word): string;
        function GetValueByIndex(Index: Word): string;
        function GetValueByKey(const Key: string): string; inline;
      public
        constructor Create;
        destructor Destroy; override;
        procedure Add(Index: Word; const Key, Value: string);
        procedure Remove(Index: Word);
        property KeyByIndex[Index: Word]: string read GetKeyByIndex;
        property ValueByIndex[Index: Word]: string read GetValueByIndex; default;
        property ValueByKey[const Key: string]: string read GetValueByKey;
      end;
    
    
    { FIndexedDidctionary }
    
    procedure FIndexedDidctionary.Add(Index: Word; const Key, Value: string);
    const
      INDEX_GROW_CHUNK = 1024;
    begin
      if Index >= Length(FIndexes) then
        SetLength(FIndexes, (Index div INDEX_GROW_CHUNK + 1) * INDEX_GROW_CHUNK);
    
      FKeyPairs.Add(Key, Value);
      FIndexes[Index] := TStringPair.Create(Key, Value);
    end;
    
    constructor FIndexedDidctionary.Create;
    begin
      FKeyPairs := TDictionary<string, string>.Create;
    end;
    
    destructor FIndexedDidctionary.Destroy;
    begin
      FKeyPairs.Free;
    end;
    
    function FIndexedDidctionary.GetKeyByIndex(Index: Word): string;
    begin
      if Index >= Length(FIndexes) then
        Exit(''); // при желании можно заменить на raise Exception
      Result := FIndexes[Index].Key;
    end;
    
    function FIndexedDidctionary.GetValueByIndex(Index: Word): string;
    begin
      if Index >= Length(FIndexes) then
        Exit(''); // при желании можно заменить на raise Exception
      Result := FIndexes[Index].Value;
    end;
    
    function FIndexedDidctionary.GetValueByKey(const Key: string): string;
    begin
      Result := FKeyPairs[Key];
    end;
    
    procedure FIndexedDidctionary.Remove(Index: Word);
    begin
      if Index >= Length(FIndexes) then
        Exit; // при желании можно заменить на raise Exception
      var Item := PStringPair(@FIndexes[Index]);
      FKeyPairs.Remove(Item.Key);
      Item.Key := '';
      Item.Value := '';
    end;
    

    上面的代码是记事本的示例,我尚未对其功能进行测试。这仅意味着通过索引添加和删除元素,但不更改现有元素。

    • 0
  2. Best Answer
    Kromster
    2024-03-01T16:59:24Z2024-03-01T16:59:24Z

    @Alekcvp 给了我一个想法。

    首先,当然,你可以稍微优化一下:

    TKMLibraryKey = string;
    TKMLibraryLine = string;
    
    fText: TList<TKMLibraryLine>;
    fIndexKey: TList<TKMLibraryKey>;
    fDictionaryKeyIndex: TDictionary<TKMLibraryKey, Word>;
    

    此外,根据 @Alekcvp 的建议(仅不重复行):

    fText: TList<TPair<TKMLibraryKey, TKMLibraryLine>>;
    fDictionaryKeyIndex: TDictionary<TKMLibraryKey, Word>;
    

    总的来说,两个常用脚本的访问时间复杂度为 O(1),而一个罕见脚本则通过字典进行访问。

    内存占用 -(V, K, K + I) * n

    • 0

相关问题

  • 查找数值

  • 如何在 DBGrid 中选择 DBDateTimeEditEh 编辑记录字段?

  • 该程序无法在 RAD STUDIO 10.3 中编译或运行

  • 我们需要一个可视化的 Delphi 组件,类似于在旧版本的 Windows 中显示磁盘碎片整理

  • 按钮代码 OnClick 通过另一个按钮

  • 这种代码排序方法是如何工作的?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5