如何在Delphi中实现决策矩阵

时间:2012-03-06 07:10:25

标签: algorithm delphi dictionary delphi-7 boolean-logic

我必须在Delphi 7中实现决策矩阵。 功能是

  

CalcNewStatus(actionCode:string; reportType:string; currentStatus:string):string;

  • ActionCode可以包含值“A”和“N”
  • ReportType可以包含值“I”和“F”
  • CurrentStatus的值可以是'P','I','F'。

在C#中,我会使用字典。我怎么能在Delphi 7中做到这一点?

3 个答案:

答案 0 :(得分:10)

将输入字符规范化为基于零的序数值,事情变得更加容易。从几个类型声明开始:

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.

答案 1 :(得分:4)

首先在这种有限的情况下(2个ActionCodes,2个ReportTypes,3个状态)我绝对应该使用枚举类型而不是字符串。

对于决策矩阵......矩阵:

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

答案 2 :(得分:0)

有一种解决方案使用一维数组。

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.