Cómo comparar los conjuntos de tipos enumerados

votos
7

Desde cierto punto me cansé de escribir las condiciones de ajuste ( and, or), porque para más condiciones o nombres de variables más largos que comienza a ser torpe y molesto para escribir todo de nuevo. Así que empecé a escribir ayudantes para que pudiera escribir ASet.ContainsOne([ceValue1, ceValue2])en lugar de (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;

Por desgracia, esto no es la solución más eficaz y que va en contra del principio DRY. Para mi sorpresa, no he encontrado alguna vez alguien tratar con el mismo problema, así que me pregunto si hay alguna solución mejor (genérico)?

Publicado el 19/09/2018 a las 13:24
fuente por usuario
En otros idiomas...                            


2 respuestas

votos
14

Los operadores de conjunto ayudan a implementar estas funciones

Para ContainsOneusamos el *operador que es el operador de intersección de conjuntos.

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

Para ContainsAllusaríamos <=que es el operador subconjunto.

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

Teniendo en cuenta lo simple que estas expresiones son, me pregunto si necesita o no el tipo de ayuda en absoluto.

La documentación da la lista completa de los operadores de conjuntos disponibles.

Respondida el 19/09/2018 a las 13:42
fuente por usuario

votos
4

Se puede utilizar el operador de intersección de conjuntos

Para ContainsOnecheque analógica si la intersección no es conjunto vacío, para la ContainsAllcomprobación de esa intersección coincide con juego de argumento

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');
Respondida el 19/09/2018 a las 13:35
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more