Delphi 如何在记录数组中按字段查找特定记录

Delphi 如何在记录数组中按字段查找特定记录,delphi,Delphi,我知道这可能是一个基本的问题,但问题来了。 我定义了一个常量记录数组: TDocumentKindInfo = record Employee: integer; First: string; Last: string; Title: string; end; const CDocumentKindInfos: array[TDocumentKind] of TDocumentKindInfo = ( (Emplyee: 1; First

我知道这可能是一个基本的问题,但问题来了。 我定义了一个常量记录数组:

  TDocumentKindInfo = record

    Employee: integer;
    First: string;
    Last: string;
    Title: string;
  end;

const
  CDocumentKindInfos: array[TDocumentKind] of TDocumentKindInfo = (

    (Emplyee: 1; First: 'Bob'; Last: 'Fredricks'; Title: 'Manager'),
    (Emplyee: 2; First: 'Bill'; Last: 'Evans'; Title: 'Cashier'),
    (Emplyee: 3; First: 'Jill'; Last: 'Dunne'; Title: 'Stocker'),
...
如何找到作为经理的员工姓名。我环顾四周,找不到任何有用的东西。我是德尔菲的初学者。使用Delphi7。

尝试以下代码

for I:= Low(CDocumentKindInfos) to high(CDocumentKindInfos) do
begin
  if CDocumentKindInfos[I].Title = 'Manager' then
  begin
    ShowMessage('Employee name is ' + CDocumentKindInfos[I].Employee);
    Break;
  end;
end;

我通常会这样写:

function FindDocumentByTitle(const Title: string): TDocumentKind;
begin
  for Result := low(Result) to high(Result) do
    if SameText(Title, CDocumentKindInfos[Result].Title) then
      exit;
  raise EDocumentNotFound.CreateFmt('Document titled ''%s'' not found.', [Title]);
end;      
type  TData = record
        Points: Integer;
        Count:  Cardinal;
        flags:  Cardinal;
      end;
      PData = ^Data;
      TDataArray = array of TData
      PDataArray = ^TDataArray
...
var   LongNameForSomeNouns: TDataArray
      Noun:  PData;         //pointer to the current Record
      iNoun: Integer;
...
  for iNoun:=Low(LongNameForSomeNouns) to High(LongNameForSomeNouns) do begin
    Noun := @LongNameForSomeNouns[iNoun];
    Noun.Points := 5;
    Inc(Noun.Count);
    SomeFunction(Noun);
  end;

如果找不到项,函数将引发错误。很快你就会在课堂上总结所有这些问题。

我意识到这个问题已经问了3年了,但我想我应该补充一下答案

在遍历记录数组时,我经常编写如下代码:

function FindDocumentByTitle(const Title: string): TDocumentKind;
begin
  for Result := low(Result) to high(Result) do
    if SameText(Title, CDocumentKindInfos[Result].Title) then
      exit;
  raise EDocumentNotFound.CreateFmt('Document titled ''%s'' not found.', [Title]);
end;      
type  TData = record
        Points: Integer;
        Count:  Cardinal;
        flags:  Cardinal;
      end;
      PData = ^Data;
      TDataArray = array of TData
      PDataArray = ^TDataArray
...
var   LongNameForSomeNouns: TDataArray
      Noun:  PData;         //pointer to the current Record
      iNoun: Integer;
...
  for iNoun:=Low(LongNameForSomeNouns) to High(LongNameForSomeNouns) do begin
    Noun := @LongNameForSomeNouns[iNoun];
    Noun.Points := 5;
    Inc(Noun.Count);
    SomeFunction(Noun);
  end;
我想提出三点:

  • 我很少使用I作为迭代器。太没意义了。相反,我使用I作为一个短词的前缀(意思是迭代器),它提醒我正在迭代什么。这样,一些错误,如“SomeVerbs[iNoun]”变得显而易见

  • 使用一个中间变量(比如Noun)作为记录指针,可以压缩代码,而不会产生“With”这个邪恶的东西。嵌套此类循环时,请使用单独的迭代器和记录指针

  • 将记录指针作为参数传递意味着Delphi永远不会复制记录。这也意味着接收功能可以修改记录。如果要传递副本,可以显式传递

  • 最后,为什么要使用记录而不是对象?演出跟踪指向指针的指针会导致缓存抖动,从而降低性能。对象数组实际上是指向对象的指针数组。每一层间接寻址都会迫使CPU将不同的内存线调用到缓存中,这会导致CPU暂停。这比只有一个固定的、小的缓存要糟糕得多。您的CPU有少量缓存线


    是的,这只对某些类型的程序重要,而且只有在分析之后。但我注意到了这一点,速度提高了50-100倍。一个过去需要一周时间来处理1000万条数据库记录的程序现在可以在一夜之间完成。它以前是CPU绑定的,现在完全是数据库IO绑定的

    或者
    SameText(CDocumentKindInfos[I].Title,'Manager')
    如果您想不区分大小写您在if中执行赋值,它将不会编译:)+1 for good循环,结果是迭代索引-这样的代码快速高效-唯一的缺点是您必须为错误指定一些超出范围的元素。您可以使用const dknown:TDocumentKind=TDocumentKind(255);若要创建一个“虚拟”TDocumentKind项目以在找不到它时返回。@a.Bouchez在没有明显的未找到哨兵的情况下,我刚刚选择了raise。我更喜欢raise例外。这样,您就不必编写9层以上的if-error-Then-exit代码。