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