Delphi 这经济吗?

Delphi 这经济吗?,delphi,delphi-xe7,Delphi,Delphi Xe7,只是想看看是否有更好的方法来执行以下操作(对于任何事情都有更好的方法),因为加载数据量会导致应用程序延迟 我想用存储在csv文件中的数据填充一个记录数组,目前数组的长度是固定的,但稍后会使其成为动态的,以便添加到csv文件中 type TStarCoords = Packed record szSystem: String[40]; fCoordX: Single; fCoordY: Single

只是想看看是否有更好的方法来执行以下操作(对于任何事情都有更好的方法),因为加载数据量会导致应用程序延迟

我想用存储在csv文件中的数据填充一个记录数组,目前数组的长度是固定的,但稍后会使其成为动态的,以便添加到csv文件中

    type
          TStarCoords = Packed record
            szSystem: String[40];
            fCoordX: Single;
            fCoordY: Single;
            fCoordZ: Single;
          end;

    SystemCoords: Array [0 .. 22379] of TStarCoords;

Const
SYSTEMS = 'Data\Systems.csv';
然后在oncreate事件上填充数组

procedure TForm1.FormCreate(Sender: TObject);
var
  szFile, sRecord: string;
  Row, Index, i: Integer;
  slList: TStringList;
begin

  szFile := ExtractFilePath(ParamStr(0)) + SYSTEMS;

  if FileExists(szFile) then
    try
      slList := TStringList.Create;
      slList.LoadFromFile(szFile);

      for Row := 0 to slList.Count - 1 do
      begin
        sRecord := slList[Row];

        index := Pos(',', sRecord);
        if index > 0 then
        begin
          SystemCoords[Row].szSystem := Copy(sRecord, 1, index - 1);
          Delete(sRecord, 1, index);
        end;

        index := Pos(',', sRecord);
        if index > 0 then
        begin
          SystemCoords[Row].fCoordX := StrToFloat(Copy(sRecord, 1, index - 1));
          Delete(sRecord, 1, index);
        end;

        index := Pos(',', sRecord);
        if index > 0 then
        begin
          SystemCoords[Row].fCoordY := StrToFloat(Copy(sRecord, 1, index - 1));
          Delete(sRecord, 1, index);
        end;

        SystemCoords[Row].fCoordZ := StrToFloat(sRecord);
      end;
    finally
      slList.Free;
    end;

  for i := Low(SystemCoords) to High(SystemCoords) do
  begin
    cbSystem.Items.Add(SystemCoords[i].szSystem);
  end;
end;
正如您所看到的,我正在使用“Pos”函数解析csv文件,并在末尾循环数组以将星型名称添加到组合框中,有没有更经济的方法


欢迎您提出任何建议

您可以使用
TStringlist
解析该行。在下面的例子中,我假设元素之间用逗号分隔

由于您将记录的字符串表示形式放入一个组合框中,因此稍后在程序中您需要使用另一种方式:从字符串中查找TStarCoords。考虑到这一点,我建议您将元素放入
t字典中
插入数组

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Generics.Collections, StdCtrls;

type
  TStarCoords = packed record
    szSystem: string[40];
    fCoordX: Single;
    fCoordY: Single;
    fCoordZ: Single;
  end;
const
  SYSTEMS = 'Data\Systems.csv';

type
  TForm1 = class(TForm)
    ComboBox1: TComboBox;
    procedure FormCreate(Sender: TObject);
    procedure ComboBox1Change(Sender: TObject);
  private
    SystemCoords: TDictionary<string, TStarCoords>;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ComboBox1Change(Sender: TObject);
var
  StarCoord: TStarCoords;
begin
  if not SystemCoords.TryGetValue(ComboBox1.Text, StarCoord) then
    exit; //todo : Make some error handling

  Caption := FloatToStr(StarCoord.fCoordX);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Lines, Elements: TStringlist;
  Line: string;
  SystemCoord: TPair<string, TStarCoords>;
begin
  if not FileExists(ExtractFilePath(ParamStr(0)) + SYSTEMS) then
    exit; //todo: Some error handling

  SystemCoords := TDictionary<string, TStarCoords > .Create;
  Lines := TStringlist.Create;
  Elements := TStringlist.Create;
  Elements.LineBreak := ',';
  try
    for Line in Lines do
    begin
      Elements.Text := Line;

      SystemCoord.Key := Elements[0];
      with SystemCoord.Value do
      begin
        szSystem := string(Elements[0]);
        fCoordX := StrToFloat(Elements[1]);
        fCoordY := StrToFloat(Elements[2]);
        fCoordZ := StrToFloat(Elements[3]);
      end;

      SystemCoords.Add(SystemCoord.Key, SystemCoord.Value);
    end;

  finally
    Lines.Free;
    Elements.Free;
  end;

  try
    ComboBox1.Items.BeginUpdate;
    for SystemCoord in SystemCoords do
      ComboBox1.Items.Add(SystemCoord.Key);
  finally
    ComboBox1.Items.EndUpdate;
  end;

end;

end.
单元1;
接口
使用
窗口、消息、系统工具、变体、类、图形、控件、窗体、,
对话框、泛型、集合、stdctrl;
类型
TStarCoords=压缩记录
szSystem:string[40];
fCoordX:单个;
fCoordY:单身;
fCoordZ:单个;
结束;
常数
SYSTEMS='Data\SYSTEMS.csv';
类型
TForm1=类(TForm)
ComboBox1:tcombox1;
过程表单创建(发送方:ToObject);
程序组合框1变更(发送方:ToObject);
私有的
系统协调:t词典;
公众的
{公开声明}
结束;
变量
表1:TForm1;
实施
{$R*.dfm}
程序TForm1.Combox1Change(发送方:ToObject);
变量
StarCoord:TStarCoords;
开始
如果不是SystemCoords.TryGetValue(ComboBox1.Text,StarCoord),则
退出//todo:进行一些错误处理
标题:=FloatToStr(StarCoord.fCoordX);
结束;
过程TForm1.FormCreate(发送方:TObject);
变量
线条、元素:TStringlist;
行:字符串;
系统协调:TPair;
开始
如果不存在文件(ExtractFilePath(ParamStr(0))+系统),则
退出//todo:一些错误处理
SystemCoords:=TDictionary.Create;
行:=TStringlist.Create;
元素:=TStringlist.Create;
Elements.LineBreak:=',';
尝试
为了排成一行吗
开始
元素。文本:=行;
SystemCoord.Key:=元素[0];
使用SystemCoord.Value do
开始
szSystem:=字符串(元素[0]);
fCoordX:=StrToFloat(元素[1]);
fCoordY:=StrToFloat(元素[2]);
fCoordZ:=StrToFloat(元素[3]);
结束;
SystemCoords.Add(SystemCoord.Key,SystemCoord.Value);
结束;
最后
行。免费;
元素。免费;
结束;
尝试
ComboBox1.Items.BeginUpdate;
对于SystemCoords中的SystemCoords do
ComboBox1.Items.Add(SystemCoord.Key);
最后
ComboBox1.Items.EndUpdate;
结束;
结束;
结束。

您可以使用
TStringlist
解析行。在下面的例子中,我假设元素之间用逗号分隔

由于您将记录的字符串表示形式放入一个组合框中,因此稍后在程序中您需要使用另一种方式:从字符串中查找TStarCoords。考虑到这一点,我建议您将元素放入
t字典中
插入数组

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Generics.Collections, StdCtrls;

type
  TStarCoords = packed record
    szSystem: string[40];
    fCoordX: Single;
    fCoordY: Single;
    fCoordZ: Single;
  end;
const
  SYSTEMS = 'Data\Systems.csv';

type
  TForm1 = class(TForm)
    ComboBox1: TComboBox;
    procedure FormCreate(Sender: TObject);
    procedure ComboBox1Change(Sender: TObject);
  private
    SystemCoords: TDictionary<string, TStarCoords>;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ComboBox1Change(Sender: TObject);
var
  StarCoord: TStarCoords;
begin
  if not SystemCoords.TryGetValue(ComboBox1.Text, StarCoord) then
    exit; //todo : Make some error handling

  Caption := FloatToStr(StarCoord.fCoordX);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Lines, Elements: TStringlist;
  Line: string;
  SystemCoord: TPair<string, TStarCoords>;
begin
  if not FileExists(ExtractFilePath(ParamStr(0)) + SYSTEMS) then
    exit; //todo: Some error handling

  SystemCoords := TDictionary<string, TStarCoords > .Create;
  Lines := TStringlist.Create;
  Elements := TStringlist.Create;
  Elements.LineBreak := ',';
  try
    for Line in Lines do
    begin
      Elements.Text := Line;

      SystemCoord.Key := Elements[0];
      with SystemCoord.Value do
      begin
        szSystem := string(Elements[0]);
        fCoordX := StrToFloat(Elements[1]);
        fCoordY := StrToFloat(Elements[2]);
        fCoordZ := StrToFloat(Elements[3]);
      end;

      SystemCoords.Add(SystemCoord.Key, SystemCoord.Value);
    end;

  finally
    Lines.Free;
    Elements.Free;
  end;

  try
    ComboBox1.Items.BeginUpdate;
    for SystemCoord in SystemCoords do
      ComboBox1.Items.Add(SystemCoord.Key);
  finally
    ComboBox1.Items.EndUpdate;
  end;

end;

end.
单元1;
接口
使用
窗口、消息、系统工具、变体、类、图形、控件、窗体、,
对话框、泛型、集合、stdctrl;
类型
TStarCoords=压缩记录
szSystem:string[40];
fCoordX:单个;
fCoordY:单身;
fCoordZ:单个;
结束;
常数
SYSTEMS='Data\SYSTEMS.csv';
类型
TForm1=类(TForm)
ComboBox1:tcombox1;
过程表单创建(发送方:ToObject);
程序组合框1变更(发送方:ToObject);
私有的
系统协调:t词典;
公众的
{公开声明}
结束;
变量
表1:TForm1;
实施
{$R*.dfm}
程序TForm1.Combox1Change(发送方:ToObject);
变量
StarCoord:TStarCoords;
开始
如果不是SystemCoords.TryGetValue(ComboBox1.Text,StarCoord),则
退出//todo:进行一些错误处理
标题:=FloatToStr(StarCoord.fCoordX);
结束;
过程TForm1.FormCreate(发送方:TObject);
变量
线条、元素:TStringlist;
行:字符串;
系统协调:TPair;
开始
如果不存在文件(ExtractFilePath(ParamStr(0))+系统),则
退出//todo:一些错误处理
SystemCoords:=TDictionary.Create;
行:=TStringlist.Create;
元素:=TStringlist.Create;
Elements.LineBreak:=',';
尝试
为了排成一行吗
开始
元素。文本:=行;
SystemCoord.Key:=元素[0];
使用SystemCoord.Value do
开始
szSystem:=字符串(元素[0]);
fCoordX:=StrToFloat(元素[1]);
fCoordY:=StrToFloat(元素[2]);
fCoordZ:=StrToFloat(元素[3]);
结束;
SystemCoords.Add(SystemCoord.Key,SystemCoord.Value);
结束;
最后
行。免费;
元素。免费;
结束;
尝试
ComboBox1.Items.BeginUpdate;
对于SystemCoords中的SystemCoords do
ComboBox1.Items.Add(SystemCoord.Key);
最后
ComboBox1.Items.EndUpdate;
结束;
结束;
结束。

它看起来效率不高

  • 分配固定长度的全局数组看起来很糟糕。使用在运行时确定长度的动态数组
  • 不建议使用短字符串。不要在现代编程中使用它们。它们是遗留的,不处理Unicode
  • 不要打包记录。这会导致数据不一致
  • 似乎需要更多的堆分配。尽可能避免
    删除
    
    
  • 加载到字符串列表将不会有效率。使用基于行读取器的方法提高速度。德尔福的内置类虽然是垃圾。如果你想快速有效地使用内存,那就自己动手吧
  • 可能大部分时间都花在填充组合上了!将22380个项目添加到
    const
      CFILENAME = '<your path to some file .dat>';
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      lstStarCoords: TList<TStarCoords>;
      f: File;
      starCoords: TStarCoords;
    begin
      lstStarCoords := TList<TStarCoords>.Create;
      try
    
        AssignFile(f, CFILENAME);
        Reset(f, SizeOf(TStarCoords));
        try
          while not Eof(f) do begin
            BlockRead(f, starCoords, 1);
            lstStarCoords.Add(starCoords);
          end;
        finally
          CloseFile(f);
        end;
    
        cbSystem.Items.BeginUpdate;
        for starCoords in lstStarCoords do
          cbSystem.Items.Add(starCoords.szSystem);
        cbSystem.Items.EndUpdate;
    
      finally
        lstStarCoords.Free;
      end;
    end;
    
    procedure TForm1.WriteStarCoords;
    var
      lstStarCoords: TList<TStarCoords>;
      f: File;
      starCoords: TStarCoords;
      i: Integer;
    begin
      lstStarCoords := TList<TStarCoords>.Create;
      try
    
        //let's insert 5k new items
        for i:=1 to 5000 do begin
          with starCoords do begin
            szSystem := 'HYEL YE';
            fCoordX := 122;
            fCoordY := 12.375;
            fCoordZ := 45.75;
          end;
          lstStarCoords.Add(starCoords);
        end;
    
        AssignFile(f, CFILENAME);
        Rewrite(f, SizeOf(TStarCoords));
        try
          for starCoords in lstStarCoords do
            BlockWrite(f, starCoords, 1);
        finally
          CloseFile(f);
        end;
    
      finally
        lstStarCoords.Free;
      end;
    end;
    
    type
      PStarCoords = ^TStarCoords;
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      lstStarCoords: TStringList;
      f: File;
      starCoords: PStarCoords;
    begin
      ClearCbSystem;
    
      lstStarCoords := TStringList.Create(False);
      {another minor enhancement:
       since lstStarCoords does not own any TObject which needs to be freed
       the OwnsObjects property of the TStringList can be set to False
       in order to avoid some code to be execute in some method like Clear and Delete}
      try
    
        lstStarCoords.BeginUpdate;
    
        AssignFile(f, CFILENAME);
        Reset(f, SizeOf(TStarCoords));
        try
          while not Eof(f) do begin
            New(starCoords);
            BlockRead(f, starCoords^, 1);
            lstStarCoords.AddObject(starCoords^.szSystem, TObject(starCoords));
          end;
        finally
          CloseFile(f);
        end;
    
        lstStarCoords.EndUpdate;
    
        cbSystem.Items.Assign(lstStarCoords);
      finally
        lstStarCoords.Free;
      end;
    end;
    
    procedure TForm1.ClearCbSystem;
    var
      i: Integer;
    begin
      cbSystem.Items.BeginUpdate;
      for i := cbSystem.Items.Count-1 downto 0 do
        Dispose(PStarCoords(cbSystem.Items.Objects[i]));
      cbSystem.Clear;
      cbSystem.Items.EndUpdate;
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      ClearCbSystem;
    end;