如何在Delphi中实现决策矩阵



我必须在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.

最新更新