首页 > 解决方案 > 如何比较枚举类型集

问题描述

从某一点开始,我厌倦了编写集合条件(and, or),因为对于更多条件或更长的变量名,重新编写开始变得笨拙和烦人。所以我开始写助手,这样我就可以写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 原则。令我惊讶的是,我没有发现任何人处理过同样的问题,所以我想知道是否有更好的(通用)解决方案?

标签: delphidelphi-10.2-tokyo

解决方案


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

因为ContainsOne我们使用的*是集合交集运算符。

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

因为ContainsAll我们将使用<=which 是子集运算符。

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

鉴于这些表达式有多简单,我怀疑你是否需要辅助类型。

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


推荐阅读