AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Anzahl der Elemente in einem Set ermitteln?
Thema durchsuchen
Ansicht
Themen-Optionen

Anzahl der Elemente in einem Set ermitteln?

Ein Thema von DieDolly · begonnen am 14. Apr 2019 · letzter Beitrag vom 25. Apr 2019
Antwort Antwort
DieDolly

Registriert seit: 22. Jun 2018
2.175 Beiträge
 
#1

Anzahl der Elemente in einem Set ermitteln?

  Alt 14. Apr 2019, 01:55
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?
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.275 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Anzahl der Elemente in einem Set ermitteln?

  Alt 14. Apr 2019, 03:02
Hallo,
einen Aufhänger müsstest Du hier schon mal gaben

https://www.delphipraxis.net/190944-...alisieren.html
Heiko
  Mit Zitat antworten Zitat
peterbelow

Registriert seit: 12. Jan 2019
Ort: Hessen
701 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
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.453 Beiträge
 
Delphi 12 Athens
 
#4

AW: Anzahl der Elemente in einem Set ermitteln?

  Alt 14. Apr 2019, 17:13
Wenn der Set-Typ tatsächlich einen deklarierten Basistyp hat, dann geht das vielleicht auch einfacher:
Result := Ord(High(TSetElement)) - Ord(Low(TSetElement))

Bei der CountOfElements-Funktion müsste man doch auch noch ein Set übergeben, daß alle Elemente des Basistyps enthält, oder? Bei einem leeren Set schlägt die if-Anweisung immer fehl.

Wenn es nur um das Zählen der im Set enthaltenen Elemente geht, geht das auch einfacher:
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 in aSet do
      Inc(Result);
  end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Dennis07

Registriert seit: 19. Sep 2011
Ort: Deutschland
485 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Anzahl der Elemente in einem Set ermitteln?

  Alt 15. Apr 2019, 04:58
Wenn du die Lina Components Library hast, dann gibt es da in der uSysTools.pas -Unit auch die Funktionen:
Delphi-Quellcode:
function Count(Elements: TByteSet): Byte; overload;
function Count(Elements: TCharSet): Byte; overload;
Diese können zumindest Byte-und Charsets zählen. Ansonsten kannst du natürlich problemlos entweder eine for -in -Schleife oder aber eine Bitzählung benutzen, wie auch weiter oben schon vorgeschlagen wurde.
Dennis
  Mit Zitat antworten Zitat
freimatz

Registriert seit: 20. Mai 2010
1.443 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Anzahl der Elemente in einem Set ermitteln?

  Alt 16. Apr 2019, 13:07
Wo ist denn hier der Kopf-an-die-Wand-schlag Button?
So was macht man nicht!
Wegen so einem set of byte statt set of spezifischen Aufzählungstyp haben wir hier schon Stunden an Fehlersuche verbracht.
Und in Zeiten von Unicode ist ein set of char auch nicht mehr sicher. Spätestens bei Surrogaten wird es dann übel.

Geändert von freimatz (16. Apr 2019 um 14:01 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.453 Beiträge
 
Delphi 12 Athens
 
#7

AW: Anzahl der Elemente in einem Set ermitteln?

  Alt 16. Apr 2019, 13:25
Wo ist denn hier der Kopf-an-die-Wand-schlag Button?
Hier:
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Dennis07

Registriert seit: 19. Sep 2011
Ort: Deutschland
485 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Anzahl der Elemente in einem Set ermitteln?

  Alt 18. Apr 2019, 01:08
Wo ist denn hier der Kopf-an-die-Wand-schlag Button?
So was macht man nicht!
Wegen so einem set of byte statt set of spezifischen Aufzählungstyp haben wir hier schon Stunden an Fehlersuche verbracht.
Und in Zeiten von Unicode ist ein set of char auch nicht mehr sicher. Spätestens bei Surrogaten wird es dann übel.
Was du benutzt ist dir überlassen.
So generell kann man halt nicht sagen was wo wie gebraucht wird. Das hängt immer vom einzelfall ab.
Wenn du etwas professionellere Sets benutzen willst, dann schau am besten mal in meine CustomSets unit. Dort findest du die TSet<T>-Klasse, die nahezu keine Wünsche übrig lässt...
Dennis
  Mit Zitat antworten Zitat
Rudy Velthuis

Registriert seit: 10. Sep 2011
Ort: Gelsenkirchen
42 Beiträge
 
Delphi 10.3 Rio
 
#9

AW: Anzahl der Elemente in einem Set ermitteln?

  Alt 25. Apr 2019, 18:28
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?
Wenn es wirklich schnell sein muss, dann kann man eine Tabelle anlegen mit 256 Einträge, und zwar jeweils die Anzahl an Bits des betreffenden Bytes. Dann nur noch eine Schleife über den Set, der die Bits pro Byte addiert. Oder 16 Einträge, mit der Anzahl bits für ein Nibble (halbes Byte). Egal wie, aber mit einer Lookup-Tabelle geht's schneller.

Schau mal hier (Cardinality of a Set, aus den alten Borland-Newsgroups): https://groups.google.com/forum/#!to...al/rh52jMoOOBI

Für ein bestimmtes Set von maximal 7 Werten würde ich eine 128-Byte Tabelle anlegen und dann:
Code:
    procedure Cardinality(ASet: DerSetTyp): Integer;
    const
      DieTabelle: array[0..127] of Byte =
      (
          0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, //  0..15
          1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, // 16..31
          1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, // 32..47
         
          // usw...

      );
    begin
      Result := DieTabelle[Byte(ASet)];
    end;
Mehr brauchst du dann nicht.
Rudy Velthuis

Geändert von Rudy Velthuis (25. Apr 2019 um 18:45 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:44 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz