Einzelnen Beitrag anzeigen

peterbelow

Registriert seit: 12. Jan 2019
Ort: Hessen
702 Beiträge
 
Delphi 12 Athens
 
#3

AW: Anzahl der Elemente in einem Set ermitteln?

  Alt 14. Apr 2019, 13:17
Wie ermittelt man am besten die Größe eines Sets oder die Anzahl an Elementen in einem Set?
Es geht um ein Set, welches maximal 7 Elemente aufnehmen kann. Als Bytewert ergibt das am Ende 127. Ich könnte gegen diese 127 prüfen aber es muss doch eine Möglichkeit geben zu ermitteln, wieviele Elemente in diesem Set sind oder nicht?
Die Größe eines Sets, in Bytes, liefert die gute alte Sizeof-Funktion. Um die Zahl der Elemente zu ermitteln, die der Set aktuell enthält, muss man sie allerdings zählen, da führt kein Weg dran vorbei. Der einfachste Ansatz ist sowas wie:
Delphi-Quellcode:
type
  TSetElement = (liste von identifiern);
  TElementSet = set of TSetElement;

  function CountOfElements(const aSet: TElementSet ): integer;
  var
    I: TSetElement;
  begin
    Result := 0;
    for I:= Low(I) to High(I) do
      if I in aSet then
        Inc(Result);
  end;
Vorteil: das ist völlig unabhängig von der Art, in der Sets implementiert sind.
Nachteil: es ist spezifisch für einen bestimmten typ von set und relativ CPU-intensiv.

Wenn man keine Skrupel hat, Kenntnis über die Art der Implementierung zu verwenden, ist es einfach, eine generelle Funktion zu schreiben, die für alle Arten von Sets funktioniert. Ein Set in Delphi ist einfach ein array of byte, und jedes gesetzte Bit repräsentiert ein im Set enthaltenes Element.


Delphi-Quellcode:
function BitCount(var aValue; size: Word): Integer;
type
{$Z-}
  Bitset = set of 0..7;
var
  proxy: array[0..High(Word) - 1] of Bitset absolute aValue;
  n: Integer;
begin
  Assert(Sizeof(Bitset) = 1);
  Result := 0;
  if Size = 0 then Exit;

  Dec(size);
  while true do begin
    if proxy[size] <> [] then
      for n := 0 to 7 do begin
        if n in proxy[size] then
          Inc(Result);
      end; { For }
    if size = 0 then
      Break;
    Dec(size);
  end; { While }
end;

Aufruf:

  LSetSize:= BitCount(aSet, Sizeof(aSet));
Das kann man noch weiter optimieren, indem man anstelle der for-Schleife einen array [byte] of integer verwendet, der für jeden möglichen Wert eines Bytes die Zahl der gesetzten Bits enthält.
Peter Below
  Mit Zitat antworten Zitat