如何比较一组枚举类型

时间:2018-09-19 13:24:42

标签: delphi delphi-10.2-tokyo

从某种意义上说,我已经厌倦了编写设置条件(andor),因为对于更多条件或更长的变量名,它变得笨拙且烦人,无法重新编写。因此,我开始写助手,以便可以写ASet.ContainsOne([ceValue1, ceValue2])而不是(ceValue1 in ASet) or (ceValue2 in ASet)

type
  TCustomEnum = (ceValue1, ceValue2, ceValue3);
  TCustomSet = set of TCustomEnum;
  TCustomSetHelper = record helper for TCustomSet 
    function ContainsOne(ASet: TCustomSet): Boolean;
    function ContainsAll(ASet: TCustomSet): Boolean;
  end;

implementation

function TCustomSetHelper.ContainsOne(ASet: TCustomSet): Boolean;
var
  lValue : TCustomEnum;
begin
  for lValue in ASet do
  begin
    if lValue in Self then
      Exit(True);
  end;
  Result := False;
end;

function TCustomSetHelper.ContainsAll(ASet: TCustomSet): Boolean;
var
  lValue : TCustomEnum;
begin
  Result := True;
  for lValue in ASet do
  begin
    if not (lValue in Self) then
      Exit(False);
  end;
end;

不幸的是,这不是最有效的解决方案,它违背了DRY原则。令我惊讶的是,我没有发现有人处理过同样的问题,所以我想知道是否有更好的(通用)解决方案?

2 个答案:

答案 0 :(得分:15)

set operators帮助您实现这些功能

对于ContainsOne,我们使用*运算符,它是设置的交集运算符。

function TCustomSetHelper.ContainsOne(ASet: TCustomSet): Boolean;
begin
  Result := ASet * Self <> [];
end;

对于ContainsAll,我们将使用<=,它是子集运算符。

function TCustomSetHelper.ContainsAll(ASet: TCustomSet): Boolean;
begin
  Result := ASet <= Self;
end;

鉴于这些表达式有多么简单,我质疑您是否根本需要帮助程序类型。

documentation提供了可用的集合运算符的完整列表。

答案 1 :(得分:4)

您可以使用set intersection operator

对于ContainsOne模拟,检查交集是否不是空集;对于ContainsAll,检查交集是否与参数集重合

type
  TCustomEnum = (ceValue1, ceValue2, ceValue3);
  TCustomSet = set of TCustomEnum;
var
  ASet: TCustomSet;
begin
  ASet := [ceValue1, ceValue3];

  if ([ceValue1, ceValue2] *  ASet) <> [] then
     Memo1.Lines.Add('Somebody here');

  if ([ceValue1, ceValue3] *  ASet) = [ceValue1, ceValue3] then
     Memo1.Lines.Add('All are in home');