Como comparar conjuntos de tipos enumerados

votos
7

De um certo ponto eu cansei de escrever condições set ( and, or), porque para mais condições ou nomes de variáveis mais longos que começa a ser desajeitado e irritante para escrever tudo de novo. Então eu comecei a escrever ajudantes para que eu pudesse escrever ASet.ContainsOne([ceValue1, ceValue2])em vez 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;

Infelizmente, esta não é a solução mais eficaz e é contra o princípio DRY. Para minha surpresa, eu não encontrei ninguém nunca lidar com o mesmo problema, então eu pergunto se há alguma solução melhor (genérico)?

Publicado 19/09/2018 em 13:24
fonte usuário
Em outras línguas...                            


2 respostas

votos
14

Os operadores de conjunto ajudar a implementar estas funções

Por ContainsOneque usar o *operador que é o operador de conjunto intersecção.

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

Para ContainsAllnós usaríamos <=que é o operador subconjunto.

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

Dado como simples estas expressões são, eu questiono se você precisa ou não do tipo ajudante em tudo.

A documentação dá a lista completa de operadores de conjunto disponíveis.

Respondeu 19/09/2018 em 13:42
fonte usuário

votos
4

Você pode usar o operador de conjunto intersecção

Para ContainsOneverificação analógica se intersecção não é conjunto vazio, para ContainsAllverificação que intersecção coincide com o conjunto 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');
Respondeu 19/09/2018 em 13:35
fonte usuário

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