如何比较枚举类型集
How to compare sets of enumerated types
从某个时候开始我就厌倦了写set conditions(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 原则。令我惊讶的是,我没有发现有人处理过同样的问题,所以我想知道是否有更好的(通用)解决方案?
您可以使用 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');
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 给出了可用集合运算符的完整列表。
从某个时候开始我就厌倦了写set conditions(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 原则。令我惊讶的是,我没有发现有人处理过同样的问题,所以我想知道是否有更好的(通用)解决方案?
您可以使用 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');
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 给出了可用集合运算符的完整列表。