Go Premium for a chance to win a PS4. Enter to Win

x
Solved

# Enumerated types and sets of - counts and loops

Posted on 2008-01-30
Medium Priority
6,992 Views
:-)
Lets say I have this.

type
TThing = (tgsOne, tgsTwo, tgsThree);
TThings = set of TThing;

and then I do

var
Things : TThings;
begin
include(Things,tgsOne);

and that is all good, Things now contains tgsOne in the set.
then I do this
include(Things,tgsTwo);

now I want to know how many items are in the set.
showmessage( IntToStr(length(Things)) );
that dosn't want to work.

Also how can I loop the items in my set to see if they are in there/do stuff. Do I have to do
var
Things : TThings;
Thing : TThing;
begin
include(Things,tgsOne);

For Thing := low(TThing) to high(Thing) do
If Thing in Things then
//-- do something

:-)

0
Question by:wildzero

LVL 17

Accepted Solution

mokule earned 336 total points
ID: 20781509
Yes You should loop this way
0

LVL 10

Author Comment

ID: 20781582
What about getting a count of the number of items in the set?
0

LVL 21

Assisted Solution

developmentguru earned 332 total points
ID: 20781818
Where you have
//-- Do Something
put in
Inc(Count);

There are faster ways of doing this.  The problem is that Delphi places sets in an appropriately sized container.  Your set would fit in one byte.  Bigger sets would use 2 or 4 bytes depending on what they need.  If you want a general function to count the number of elements in a set I would do something like the following pseudocode.  Passing an integer will type cast the set to an integer value which will allow it to handle all currently allowable set sizes.  If you need more speed than that you can use the same logic in assemly language.  Let me know if there are questions.
``````function CountSetItems(SetValue : integer) : byte;
var

begin
Count := 0;
begin
if SetValue and Mask <> 0 then
inc(Count);
end;
Result := Count;
end;
``````
0

LVL 21

Expert Comment

ID: 20781858
P.S.  the pseudo code I posted has the added advantage that it does not matter what type of set you pass it.  The down side is that it tests for values that cannot exist within a specific set (it is testing for all 32 possibilities - if your set only contains 3...).  It should be possible to create a function where you pass in the type of set and the value and it counts it by looping the appropriate number of times for the set.  I just don't have time to try it tonight, sorry.
0

LVL 21

Expert Comment

ID: 20782724
just wondering what if you do this:
Include(Things, tgsNothing);
will Things contain any elements or will it contain nothing? ;)

sorry couldn't resist:)

ziolko.
0

LVL 27

Assisted Solution

kretzschmar earned 332 total points
ID: 20784510
a small sample

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;

var
Form1: TForm1;

implementation

{\$R *.dfm}

type
TThing = (tgsOne, tgsTwo, tgsThree);
TThings = set of TThing;

function getSetCount(aSet : TThings) : integer;
var
i : TThing;
begin
result := 0;
for i := low(TThing) to high(TThing) do
begin
if (i in aset) then
inc(result);
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
ThingSet : TThings;
begin
ThingSet := [tgsOne, tgsTwo];
showmessage('Items in Set: '+inttostr(getSetCount(ThingSet)));
ThingSet := ThingSet - [tgsOne];
showmessage('Items in Set: '+inttostr(getSetCount(ThingSet)));
ThingSet := ThingSet + [tgsThree];
showmessage('Items in Set: '+inttostr(getSetCount(ThingSet)));
ThingSet := ThingSet + [tgsOne];
showmessage('Items in Set: '+inttostr(getSetCount(ThingSet)));
ThingSet := [];
showmessage('Items in Set: '+inttostr(getSetCount(ThingSet)));
end;

end.

meikl ;-)
0

LVL 1

Expert Comment

ID: 21186034
Forced accept.

Computer101
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question