我必须在Delphi7中实现一个决策矩阵。功能是
CalcNewStatus(操作代码:字符串;报告类型:字符串;当前状态:字符串):字符串;
- ActionCode可以具有值"A"one_answers"N"
- ReportType可以具有值"I"one_answers"F"
- CurrentStatus可以具有值"P"、"I"、"F"
例如,在C#中,我会使用字典。如何在Delphi 7中做到这一点?
将输入字符规范化为基于零的序数值,事情就变得容易多了。从几个类型声明开始:
type
TActionCode = (acA, acN);
TReportType = (rtI, rtF);
TStatus = (sP, sI, sF);
然后,您可以使用这些类型和所有可能的状态值来定义数组。将sX
替换为每个点中所属的状态值。
const
NextStatus: array[TActionCode, TReportType, TStatus] of TStatus = (
{acA} (// sP, sI, sF
{rtI} ( sX, sX, sX),
{rtF} ( sX, sX, sX)
),
{acN} (
{rtI} ( sX, sX, sX),
{rtF} ( sX, sX, sX)
)
);
那么你的功能就是:
function CalcNewStatus(const actionCode, reportType, currentStatus: string): string;
var
ac: TActionCode;
rt: TReportType;
s: TStatus;
const
StateChars: array[TState] of Char = ('P', 'I', 'F');
begin
Assert(actionCode <> ''); Assert(reportType <> ''); Assert(currentStatus <> '');
Assert(actionCode[1] in ['A', 'N']);
Assert(reportType[1] in ['I', 'F']);
Assert(currentStatus[1] in ['P', 'I', 'F']);
if actionCode[1] = 'A' then ac := acA else ac := acN;
if reportType[1] = 'I' then rt := rtI else rt := rtF;
if currentStatus[1] = 'P' then s := sP
else if currentStatus[1] = 'I' then s := sI
else s := sF;
Result := StateChars[NextStatus[ac, rt, s]];
end;
正如您所看到的,这些代码的大部分都是在字符串和枚举类型之间转换的。如果可以的话,在这种情况下要避免字符串。在程序中尽可能早地切换到枚举类型,只有在绝对需要的时候才能转换回字符串或字符。字符串可以有任意长度,这是你不应该处理的,字符串的值也可以超出你定义的范围。枚举不能,除非你做了一些奇怪的事情。此外,编译器不会让您意外地在需要TReportType的地方使用TState值,这将帮助您避免混淆I和F。
首先,在这种有限的情况下(2个ActionCodes、2个ReportTypes、3个Statues),我肯定应该使用枚举类型而不是字符串。
对于决策矩阵。。。矩阵:
Type
TActionCode = (taA, taN);
TReprotType = (rtI, rtF);
TStatus = (stP, stI, stF);
const
NewStatus: array [TActionCode, TReportType, TStatus] of TStatus =
((((,,)),((,,))),(((,,)),((,,)))) // values of the new statuses here
有一种解决方案使用一维数组。
unit XnResultStatusOverride;
interface
function XnCalcOverridenResultStatus(
actionCodeStr: string;
reportTypeStr: string;
currentStatusStr: string ): string;
implementation
uses SysUtils;
type
TActionCodes = ( ActionCodeA = 0, ActionCodeN = 1);
TReportTypes = (ReportTypeI = 0, ReportTypeF = 1);
TResultStatus = (ResultStatusP = 0, ResultStatusF = 1, ResultStatusI = 2);
const
DecisionMatrix: array[ 0 .. 15 ] of TResultStatus
=
(
ResultStatusF, // 0 A-I-P
ResultStatusF, // 1 A-I-F
ResultStatusF, // 2 A-I-I
ResultStatusF, // 3 N/A
ResultStatusP, // 4 A-F-P
ResultStatusP, // 5 A-F-F
ResultStatusF, // 6 A-F-I
ResultStatusF, // 7 N/A
ResultStatusF, // 8 N-I-P
ResultStatusF, // 9 N-I-F
ResultStatusP, // 10 N-I-I
ResultStatusF, // 11 N/A
ResultStatusF, // 12 N-F-P
ResultStatusI, // 13 N-F-F
ResultStatusF, // 14 N-F-I
ResultStatusF // 15 N/A
);
function ParseActionCodeString( value: string ): TActionCodes;
begin
if value = 'A' then
begin
result := ActionCodeA;
exit;
end;
if value = 'N' then
begin
result := ActionCodeN;
exit;
end;
raise Exception.Create('Invalid action code string' );
end;
function ParseReportTypeString( value: string ): TReportTypes;
begin
if value = 'I' then
begin
result := ReportTypeI;
exit;
end;
if value = 'F' then
begin
result := ReportTypeF;
exit;
end;
raise Exception.Create('Invalid report type string' );
end;
function ParseResultStatusString( value: string ): TResultStatus;
begin
if value = 'P' then
begin
result := ResultStatusP;
exit;
end;
if value = 'F' then
begin
result := ResultStatusF;
exit;
end;
if value = 'I' then
begin
result := ResultStatusI;
exit;
end;
raise Exception.Create('Invalid result status string' );
end;
function ResultStatusToString( value: TResultStatus ): string;
begin
if value = ResultStatusP then
begin
result := 'P';
exit;
end;
if value = ResultStatusF then
begin
result := 'F';
exit;
end;
if value = ResultStatusI then
begin
result := 'I';
exit;
end;
raise Exception.Create('Unknown TResultStatus enum member' );
end;
function XnCalcOverridenResultStatus(
actionCodeStr: string;
reportTypeStr: string;
currentStatusStr: string ): string;
var
actionCode: TActionCodes;
reportType: TReportTypes;
currentStatus:TResultStatus;
discriminant: integer;
newStatusInt: integer;
newStatus: TResultStatus;
begin
actionCode := ParseActionCodeString( actionCodeStr );
reportType := ParseReportTypeString( reportTypeStr );
currentStatus := ParseResultStatusString( currentStatusStr );
discriminant := integer(actionCode) * 8 + integer(reportType) * 4 + integer(currentStatus);
newStatusInt := DecisionMatrix[ discriminant ];
newStatus := TResultStatus( newStatusInt);
Result := ResultStatusToString( newStatus );
end;
end.