Delphi 高效处理大数据量的字典数据的查询问题

一、需求

系统中存在基本字典数据,且数据量大,需要根据各种条件查询某个字典数据,该如何高效实现?

例如:系统中的菜品字典数据,需要根据菜品ID、菜品编码、菜品名+菜品规格等条件查找菜品

二、思路

1、使用索引的方法

将每个查询条件都建立一个TStringList,并添加条件值,并确保其与菜品对象 TMenuItem 在TList中的位置一样。 查询时,根据条件值找到TStringList中的位置 index,然后直接通过TList[index] 获取菜品对象。

该方法查询时不用遍历整个 TList ,从而提高查询效率。

2、使用哈希方法

将每个查询条件添加到 TDictionary 字典 TFMenuItemHash(TDictionary<string, TMenuItem>),Key 值为 【条件前缀+菜品对应ID等值】,Value 值为 TMenu 对象地址。查询时,通过FMenuItemHash.TryGetValue 获取。

注意:程序结束时,需要遍历 TFMenuItemHash,释放 TFMenuItemHash 对应的 TMenu 对象

三、代码实现

这里只展示思路2对应的代码实现。

unit uMenuItem;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, 
  System.Classes, System.Generics.Collections;

//定义查询条件类型  按菜品ID  菜品Key  菜品编码  菜品名称  菜品名称+规格  菜品ID+规格
type
  TMenuItemListType = (mltID, mltKey, mltCode, mltName, mltNameUnit, mltIDUnit, mltKeyUnit);
const
  MenuItemListTypeArry: array [TMenuItemListType] of string = ('mltID', 'mltKey', 'mltCode', 'mltName', 'mltNameUnit', 'mltIDUnit', 'mltKeyUnit');

type
  //菜品类
  TMenuItem = class
    //...菜品ID、菜品名等属性
  end;

  //菜品字典列表类
  TMenuItemLst = class
  private
    FMenuItemHash: TDictionary<string, TMenuItem>;
    //添加Key值到 FMenuItemHash 中
    procedure AddMenuItem(MenuItemType: TMenuItemListType; AKey: string; AMenuItem: TMenuItem);
    //从 FMenuItemHash 中获取 key 值对应的 TMenuItem 对象
    function GetMenuItem(MenuItemType: TMenuItemListType; AKey: string): TMenuItem;

    function InitData(): boolean;
    function GetCount: integer;
    function GetItems(Index: integer): TMenuItem;
  protected
    FList: TList<TMenuItem>;
  public
    constructor Create(); overload;
    destructor Destroy; override;

    property Count: integer read GetCount;
    property Items[Index: integer]: TMenuItem read GetItems; default;

    procedure Clear;
    procedure ClearFoodCannotSaleList;

    procedure Delete(iIndex: integer);
    function IndexOf(AMenuItem: TMenuItem): integer;
    function Refresh(): Boolean;
    
    //按菜品ID查询
    function GetMenuItemByFoodID(AFoodID: int64): TMenuItem;
    //按菜品规格查询
    function GetMenuItemByUnitKey(AUnitKey: string): TMenuItem;
    //按菜品编码查询
    function GetMenuItemByFoodCode(AFoodCode: string): TMenuItem;
    //按菜品名称查询
    function GetMenuItemByFoodName(AFoodName: string): TMenuItem;
    //按菜品名称+规格查询
    function GetMenuItemByFoodNameUnit(AFoodName, AFoodUnit: string): TMenuItem;
    //按菜品ID+规格查询
    function GetMenuItemByFoodIDUnit(AFoodID: int64; AFoodUnit: string): TMenuItem;
    //按菜品Key+规格查询
    function GetMenuItemByFoodKeyUnit(AFoodKey, AFoodUnit: string): TMenuItem;
end;

implementation

{ TMenuItemLst }

procedure TMenuItemLst.Clear;
var
  i: integer;
begin
  for i := 0 to FList.Count - 1 do
  begin
    FList[i].Free;
  end;

  FList.Clear;
  FMenuItemHash.Clear;
end;


constructor TMenuItemLst.Create;
begin
  FList := TList<TMenuItem>.Create;
  FMenuItemHash := TDictionary<string, TMenuItem>.Create;
end;

procedure TMenuItemLst.Delete(iIndex: integer);
begin
  TMenuItem(FList[iIndex]).Free;
  FList.Delete(iIndex);
end;

destructor TMenuItemLst.Destroy;
begin
  Clear;
  FList.Free;
  FMenuItemHash.Free;
  inherited;
end;

function TMenuItemLst.GetCount: integer;
begin
  Result := FList.Count;
end;

procedure TMenuItemLst.AddMenuItem(MenuItemType: TMenuItemListType;
  AKey: string; AMenuItem: TMenuItem);
begin
  FMenuItemHash.AddOrSetValue(MenuItemListTypeArry[MenuItemType] + AKey, AMenuItem);
end;

function TMenuItemLst.GetMenuItem(MenuItemType: TMenuItemListType;
  AKey: string): TMenuItem;
begin
  FMenuItemHash.TryGetValue(MenuItemListTypeArry[MenuItemType] + AKey, Result);
end;

function TMenuItemLst.GetItems(Index: integer): TMenuItem;
begin
  Result := nil;
  if (Index >= 0) and (Index < FList.Count) then
    Result := TMenuItem(FList[Index]);
end;

function TMenuItemLst.GetMenuItemByFoodCode(AFoodCode: string): TMenuItem;
begin
  Result := GetMenuItem(mltCode, AFoodCode);
end;

function TMenuItemLst.GetMenuItemByFoodID(AFoodID: int64): TMenuItem;
begin
  Result := GetMenuItem(mltID, AFoodID.ToString);
end;

function TMenuItemLst.GetMenuItemByFoodIDUnit(AFoodID: int64;
  AFoodUnit: string): TMenuItem;
begin
  Result := GetMenuItem(mltIDUnit, AFoodID.ToString + AFoodUnit);
end;

function TMenuItemLst.GetMenuItemByFoodKeyUnit(AFoodKey,
  AFoodUnit: string): TMenuItem;
begin
  Result := GetMenuItem(mltKeyUnit, AFoodKey + AFoodUnit);
end;

function TMenuItemLst.GetMenuItemByFoodName(AFoodName: string): TMenuItem;
begin
  Result := GetMenuItem(mltName, AFoodName);
end;

function TMenuItemLst.GetMenuItemByFoodNameUnit(AFoodName,
  AFoodUnit: string): TMenuItem;
begin
  Result := GetMenuItem(mltNameUnit, AFoodName + AFoodUnit);
end;

function TMenuItemLst.GetMenuItemByUnitKey(AUnitKey: string): TMenuItem;
begin
  Result := GetMenuItem(mltKey, AUnitKey);
end;

function TMenuItemLst.IndexOf(AMenuItem: TMenuItem): integer;
begin
  Result := FList.IndexOf(AmenuItem);
end;

function TMenuItemLst.InitData(): boolean;
var
  i: integer;
  menuItem: TMenuItem;
  foodID, foodUnitKey, foodCode, foodName, foodUnit: string;
begin
  result := false;
  try
    try
      //循环数据集, 假如已从数据库中查询了所有菜品字典数据
      for i := 0 to 10000 do
      begin
        //初始化菜品对象,在 TMenuItemLst 类释放时,需要循环释放 TMenuItem
        menuItem := TMenuItem.Create();
        
        foodID := menuItem.FoodID;
        foodUnitKey := menuItem.FoodUnitKey;
        foodCode := menuItem.FoodCode;
        foodName := menuItem.FoodName;
        foodUnit := menuItem.FoodUnit;

        if foodID <> '' then           //添加菜品ID的Key值
          AddMenuItem(mltID, foodID, menuItem);
        if foodUnitKey <> '' then      //添加菜品Key的Key值
          AddMenuItem(mltKey, foodUnitKey, menuItem);
        if FoodCode <> '' then         //添加菜品编码的Key值
          AddMenuItem(mltCode, foodCode, menuItem);
        if foodName <> '' then
          AddMenuItem(mltName, foodName, menuItem);
        if (foodName <> '') or (foodUnit <> '') then
          AddMenuItem(mltNameUnit, foodName + foodUnit, menuItem);
        if (foodID <> '') or (foodUnit <> '') then
          AddMenuItem(mltIDUnit, foodID + foodUnit, menuItem);
        if (foodUnitKey <> '') or (foodUnit <> '') then
          AddMenuItem(mltKeyUnit, foodUnitKey + foodUnit, menuItem);

        FList.Add(menuItem);
      end;

      result := true;
    except
      on E: Exception do
      begin
        raise Exception.Create(E.Message);
      end;
    end;
  finally

  end;
end;

function TMenuItemLst.Refresh(): Boolean;
begin

end;

end.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/606988.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

力扣HOT100 - 153. 寻找旋转排序数组中的最小值

解题思路&#xff1a; 与33题类似。 class Solution {public int findMin(int[] nums) {int l 0;int r nums.length - 1;if (nums[r] > nums[l]) return nums[0];while (l < r) {int mid l (r - l) / 2;if (nums[0] > nums[mid]) {r mid - 1;} else {l mid 1…

如何在树莓派 Raspberry Pi中本地部署一个web站点并实现无公网IP远程访问

文章目录 前言1. 安装 Raspberry Pi OS2. 测试 web 站点3. 安装静态样例站点4. 将web站点发布到公网4.1 安装 Cpolar4.2 cpolar进行token认证4.3 生成cpolar随机域名网址4.4 生成cpolar二级子域名4.5 将参数保存到cpolar配置文件中4.6 测试修改后配置文件4.7 配置cpolar服务开机…

100G ZR4 80KM光模块产品亮点有哪些

之前的文章我们介绍了100G ZR4 80KM光模块的产品特征以及技术原理等&#xff0c;那本期文章我们来了解一下易天第二代100G ZR4 80KM光模块的产品亮点。 首先我们通过下面这张表格以最直观的方式来了解第一代和第二代100G ZR4 80KM光模块在工作温度、功耗、FEC纠错等方面有哪些…

Vue CLI配置代理、2.0、3.0

一、vue cli2.0 代理配置 proxy: {/api:{target: "http://localhost:8067",pathRewrite: {/api: }}, } 一、vue cli3.0 代理配置 proxy: {/api: {target: http://localhost:8067,pathRewrite: {/api: }} }

文件快递柜-免费开源-FileCodeBox

像拿快递一样取文件 什么FileCodeBox FileCodeBox 中文名是 文件快递柜&#xff0c;取文件像取快递一样&#xff0c;支持通过匿名口令分享文本&#xff0c;文件。 很多时候&#xff0c;我们都想将一些文件或文本传送给别人&#xff0c;或者跨端传递一些信息&#xff0c;但是我…

商务分析方法与工具(六):Python的趣味快捷-字符串巧妙破解密码本、身份证号码、词云图问题

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

vue路由知识补充(updating···)

1路由守卫中的next() next()方法表示放行&#xff0c;如果不执行此方法路由不会跳转&#xff0c;此方法可以接收一个参数 字符串路径&#xff1a;如果传递一个字符串路径&#xff0c;那么路由会重定向到该路径。 next(/home); 路由对象&#xff1a;如果传递一个路由对象&…

MySQL#MySql数据库的操作

目录 一、创建数据库 二、字符集和校验规则 1.查看系统默认字符集以及校验规则 2.查看数据库支持的字符集 3.查看数据库支持的字符集校验规则 4.校验规则对数据库的影响 1.以UTF-8格式创建数据库 2.不区分大小写 3.区分大小写 4 大小写对数据库的影响 三、操纵数据…

C++从入门到入土(二)——初步认识类与对象

目录 前言 类与对象的引入 类的定义 类的访问限定符及封装 访问限定符&#xff1a; 封装&#xff1a; 类的作用域 类的实例化 类的大小 this指针 this指针的特性 前言 各位佬们&#xff0c;在开始本篇文章的内容之前&#xff0c;我想先向大家道个歉&#xff0c;由于…

跨越智能建筑桥梁:西门子PLC无缝对接BACnet楼宇自动化系统化

智能楼宇每一个环节的互联互通都至关重要&#xff0c;而PLC&#xff08;可编程逻辑控制器&#xff09;作为自动化领域的基石&#xff0c;其与BACnet协议的融合无疑成为了构建智能楼宇神经系统的关键节点。今天&#xff0c;让我们深入探讨如何利用先进的PLC转BACnet协议网关&…

Windows平台PyCharm之PySide6开发环境搭建与配置

PySide6 是一个用于创建跨平台 GUI 应用程序的库&#xff0c;它是 Qt for Python 的官方库。Qt 是一个跨平台的 C 应用程序框架&#xff0c;用于开发具有图形用户界面&#xff08;GUI&#xff09;的应用程序。PySide6 允许开发者使用 Python 语言访问 Qt 的功能&#xff0c;从而…

从一毫秒到十秒:“最纯硅”激增相干时间,引领百万量子比特芯片革命

“量子计算的未来正在崭露头角”——至少专家们是这么认为的。 量子计算机并非使用传统计算中的常规1和0&#xff0c;而是利用量子物理学那些神奇的特性&#xff0c;以指数级速度执行某些计算任务。然而&#xff0c;制造一台实用的大型量子计算机面临着巨大的挑战&#xff0c;其…

Centos中将UTC的时区改为CTS时区

date命令可以看到现在的时间以及时区&#xff0c;可以看到现在是UTC时区 而想要更改时区那么就要了解tzselect命令 tzselect 是一个 Linux 命令行工具&#xff0c;用于交互式地帮助用户选择并设置系统的时区。这个程序会通过一系列的问题引导用户&#xff0c;从而确定用户所在的…

Linux命名管道的创建及应用

目录 一、命名管道的定义即功能 1.1创建命名管道 1.2匿名管道和命名管道的区别 1.3命名管道的打开规则 1.4系统调用unlink 二、进程间命名管道的创建及使用 2.1Comm.hhp 2.2PipeServer.cc 2.3PipeClient.cc 一、命名管道的定义即功能 管道应用的一个限制就是只能在具有…

动手学机器学习15 实战kaggle比赛

动手学机器学习15 实战kaggle比赛 1. 实战kaggle比赛&#xff1a;预测房价代码结果 2. 课程竞赛&#xff1a;加州2020年房价预测3. QA4. 用到的代码1. hashlib.sha1()2. sha1.update(data)3. train_data.iloc4. fillna(0)5. pd.get_dummies(&#xff09;6. nn.MSELoss()7. torc…

Linux网络部分——部署YUM仓库及NFS共享服务

目录 一、yum仓库服务 1. 软件仓库的提供方式 2.如何构建并使用ftp软件仓库&#xff08;与本地yum源方法一致&#xff09; 3.如何搭建使用yum在线源&#xff1f; 4.yum软件包下载如何保存&#xff1f; 二、NFS共享存储服务 1.存储类型 2.提供共享存储的组合 3.NFS网络…

带你快速了解并掌握TypeScript

TypeScript &#x1f4cc;TypeScript(简称:TS)是微软推出的开源语言 &#x1f4cc;TypeScript 是 JavaScript 的超集(JS 有的 TS 都有) &#x1f4cc;TypeScript Type JavaScript(在 JS 基础上增加了类型支持) &#x1f4cc;TypeScript 文件扩展名为 ts &#x1f4cc;TypeScri…

JMeter断言介绍

JMeter是一个功能强大的性能测试工具&#xff0c;它不仅可以模拟用户的行为&#xff0c;还可以对web应用程序的响应进行检测。其中断言就是JMeter中非常实用的功能之一。 断言是用于验证服务器响应是否正确的测试元素。它会检查服务器响应中的部分或全部内容&#xff0c;并在响…

[NSSRound#1 Basic]basic_check

[NSSRound#1 Basic]basic_check 开题什么都没有&#xff0c;常规信息搜集也无效 发现题目允许PUT的两种做法&#xff1a; 1、 CURL的OPTIONS请求方法查看允许的请求方式 curl -v -X OPTIONS http://node4.anna.nssctf.cn:28545/index.php2、 kali自带的nikto工具扫描网址 Nik…

vscode调试typescript(单文件)

环境 tsc: Version 5.4.5 ts-node: v10.9.2 node: v20.12.0 步骤 1.创建文件夹&#xff0c;下方创建一个index.ts。 function test() {let str: string Hello world.console.log(str) } test()2.安装ts调试插件。 3.点击VSCode的运行和调试Tab&#xff08;第三个&#xff…
最新文章