开发者

How do I find a specific record by field in an array of records

I know this is probably a basic question but here goes. I have a const array of records defined:

  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'),
...

how do I find the Employee name who is the manager. I looked aroun开发者_Go百科d and couldn't find anything that helped. I'm a beginner to delphi. Using delphi 7.


I'd normally write it like this:

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;      

The function raises an error if no item can be found. Pretty soon you'll be looking to wrap all this up in classes.


try this code

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;


I realize the question is 3 years old, but thought I'd add to the answers.

When iterating through an array of records, I often code like this:

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;

Three points I'd like to make:

  1. I seldom use i for an iterator. Too meaningless. Instead, I use i as a prefix (meaning iterator) to a short term that reminds me what is being iterated. This way some errors like 'SomeVerbs[iNoun]' become obvious.

  2. Using an intermediate variable like Noun as a Record Pointer compacts my code without the evil that is 'With'. When you nest such loops, use separate iterators and Record Pointers.

  3. Passing Record Pointers as parameters means Delphi will never make a copy of the Record. It also means the receiving function can modify the Record. If you want to pass a copy, you can do so explicitly.

Finally, why use Records instead of Objects? Performance. Following pointers to pointers causes cache-thrashing, which kills performance. An array of Objects is actually an array of pointers to Objects. Each layer of indirection forces the CPU to call a different line of memory into cache, which can stall the CPU. It's far worse than just having a fixed, small cache. Your CPU has a small number of cache lines.

Yes, that only matters for certain types of programs, and only after profiling. But I've gotten speed improvements of 50-100x by paying attention to things like that. One program that used to take a week to process 10M database records now finishes overnight. Where it used to be CPU bound it's now entirely Database IO bound.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜