如何比较枚举类型的集合

9

从某个时候开始,我厌倦了编写条件语句(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个回答

16

集合运算符可以帮助您实现这些功能。

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

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

对于ContainsAll,我们会使用子集运算符<=

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

鉴于这些表达式的简单性,我怀疑您是否需要帮助类型。 文档提供了可用集合运算符的完整列表。

谢谢你和@MBo,我不知道这个,我希望至少在这里有一个链接到那个表格Structured Types - Sets。你是对的,在这种情况下,助手是无用的。 - Triber
确实有一个关于那个主题的链接。阅读到底部。 - David Heffernan

5
你可以使用集合交集运算符
对于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');

像这样实现ContainsAll是错误的。你应该使用子集运算符,就像我的答案所示。 - David Heffernan
@David Heffernan,出了什么问题?我们可以干预编辑,但我在我的更正中没有看到ContainsAll的错误实现。刚在Delphi中检查过了。 - MBo
我的意思是,这样写虽然可行,但是s1 * s2 = s1s1 <= s2不够优雅。我原本想对你的答案进行修改,因为它基本上是正确的,但后来我们开始交叉编辑,所以我写了另一个答案。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接