问题
From a certain point I got tired of writing set conditions (and
, or
), because for more conditions or longer variable names it begins to be clumsy and annoying to write all over again. So I started writing helpers so I could write ASet.ContainsOne([ceValue1, ceValue2])
instead of (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;
Unfortunately, this is not the most effective solution and it's against the DRY principle. To my surprise, I didn't find anyone ever dealing with the same problem, so I wonder if there is any better (generic) solution?
回答1:
The set operators help you implement these functions
For ContainsOne
we use the *
operator which is the set intersection operator.
function TCustomSetHelper.ContainsOne(ASet: TCustomSet): Boolean;
begin
Result := ASet * Self <> [];
end;
For ContainsAll
we would use <=
which is the subset operator.
function TCustomSetHelper.ContainsAll(ASet: TCustomSet): Boolean;
begin
Result := ASet <= Self;
end;
Given how simple these expressions are, I question whether or not you need the helper type at all.
The documentation gives the full list of available set operators.
回答2:
You can use the set intersection operator
For ContainsOne
analog check if intersection is not empty set, for ContainsAll
check that intersection coincides with argument set
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');
来源:https://stackoverflow.com/questions/52406947/how-to-compare-sets-of-enumerated-types