How to compare sets of enumerated types

  • A+

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?


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.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: