这很经济吗?

时间:2015-10-26 06:03:14

标签: delphi delphi-xe7

只是想知道是否有更好的方法来执行以下操作(总有一种更好的方法可以解决所有问题),因为在加载时会因应用数据而延迟应用程序。

我想用我存储在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文件的函数,并在最后循环数组以将星名添加到组合框中,是否有更经济的方法呢?

欢迎任何建议

3 个答案:

答案 0 :(得分:4)

它看起来效率不高。

  • 分配固定长度的全局数组看起来很糟糕。使用在运行时确定的动态长度数组。
  • 不建议使用短字符串。不要在现代编程中使用它们。它们是遗留的,不会处理Unicode。
  • 不要打包记录。这导致数据错位。
  • 似乎需要更多的堆分配。如果可以,请避免使用Delete
  • 加载到字符串列表中不会有效。使用基于行阅读器的方法来提高速度。德尔福的内置课程虽然是垃圾。如果你想要速度和有效使用内存,请自己动手。
  • 可能大部分时间花在填充组合上!将22380项添加到组合将需要很长时间。不要这样做。如果数据集较小,则只添加数据中的项目数。否则,请在UI控件中使用虚拟范例。

你的下一步是解决瓶颈问题。我们只能猜测,因为我们缺少这么多信息。我们不知道数据是静态的,有多大,等等。

答案 1 :(得分:2)

您可以使用<li><a href="<?php echo base_url();?>index.php/login">Login</a></li> <li><a href="<?php echo base_url();?>index.php/aboutus" >About Us</a></li> 来解析该行。在下面我假设你有用逗号分隔的元素。

由于你将你的记录的字符串表示放入一个组合框我告诉你,你以后在你的程序中需要另一种方法:从字符串中找到一个TStarCoords。鉴于我在重新考虑你将你的元素放在TStringlist instread和数组中。

TDictionary

答案 2 :(得分:2)

像其他人所说,可能大部分时间花在填充组合上。

在我看来,当处理TStrings BeginUpdate提出的EndUpdate / Jens Borrisholt's answer技术的重大更新时,BlockRead构成了一种有效的方法。

作为一个小问题,如果您的应用程序是唯一一个写入和读取数据的应用程序,并且机器和人类都不关心CSV格式,您可以考虑使用{{3}来存储采用不同文件格式的记录。 }和BlockWrite函数。

type
  TStarCoords = record
    szSystem: string[40];
    fCoordX,
    fCoordY,
    fCoordZ: Single;
  end;

。 。

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;

编辑:使用指针将记录信息直接存储在cbSystem组件中的示例。

这种做法多一点危险&#34;因为它分配了必须手动释放的内存,但允许避免使用TDictionaryTStarCoords.szSystem与相应的记录配对。

声明一个指向TStarCoords记录的新类型:

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;

使用cbSystem.Clear清除列表不会自动处理必须手动释放的基础指针。每次必须清除ClearCbSystem列表时使用cbSystem程序:

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;

当表单被销毁时,对ClearCbSystem过程的调用可确保在应用程序本身释放cbSystem组件之前释放指针:

procedure TForm1.FormDestroy(Sender: TObject);
begin
  ClearCbSystem;
end;