2011-03-11 97 views
2

我知道这可能是一个基本问题,但在这里。 我有记录的常量数组定义:我如何根据记录数组中的字段找到特定的记录

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

如何找到员工的名字谁是经理。我环顾四周,找不到任何有帮助的东西。我是德尔菲的初学者。用Delphi 7

回答

6

我通常把它写这样的:

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;  

的函数抛出一个错误,如果任何项目都可以找到。很快你就会想要把所有这些都包装在课堂上。

+0

+ +1对于循环良好的循环结果作为迭代索引 - 此类代码快速且高效 - 唯一的缺点是您必须指定一些超出范围的元素以指出错误。你可以使用const dkUnknown:TDocumentKind = TDocumentKind(255);创建一个“虚拟”TDocumentKind项目,如果找不到它就返回。 – 2011-03-11 17:15:55

+0

@ A.Bouchez在没有明显的未发现哨兵的情况下,我刚选择加注。 – 2011-03-11 17:19:21

+0

我更喜欢引发异常。然后,您不必编写9层以上的错误,然后退出代码。 – 2011-03-11 20:00:00

2

试试这个代码

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; 
+0

或'SameText(CDocumentKindInfos [I] .title伪,“经理”),'如果你想不区分大小写 – 2011-03-11 14:50:13

+0

感谢,做它 - 鲍勃 – 2011-03-11 15:07:37

+2

你正在做的一个作业,如果,它不会编译:) – jachguate 2011-03-11 16:41:15

0

我意识到问题是3岁,但认为我会增加答案。

当通过一组记录迭代,我经常这样的代码:

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; 

三点我想提出:

  1. 我很少用我的迭代器。太无意义了。相反,我使用i作为前缀(意思是迭代器)来短时间提醒我什么是迭代。这样一些错误,如“SomeVerbs [iNoun]”变得明显。

  2. 使用像Noun这样的中间变量作为记录指针可以压缩我的代码,而不会使用'With'这个邪恶的东西。当你嵌套这样的循环时,使用单独的迭代器和记录指针。

  3. 传递记录指针作为参数意味着德尔福永远不会制作记录的副本。这也意味着接收功能可以修改记录。如果你想传递一份副本,你可以明确地做。

最后,为什么使用记录而不是对象?性能。以下指针指向导致高速缓存抖动,从而导致性能下降。对象数组实际上是指向对象的指针数组。每一层间接强制CPU将不同的内存线调入高速缓存,这可能会使CPU停顿。这远比只有一个固定的小缓存更糟糕。你的CPU有少量的缓存行。

是的,这只对特定类型的程序很重要,并且只在分析之后。但通过关注这样的事情,我已经获得了50-100倍的速度提升。一个过去需要一周处理10M数据库记录的程序现在在一夜之间完成。它曾经被CPU绑定,现在它完全是数据库IO绑定。

相关问题