Introduction

Unlike other programming languages like Pascal, a group data type does not exist in C#. That is the reason why I decided to write such a class to represent a group type.

Background

The two main basic ideas of group type are:

The order is not important, therefore the groups {1,2,3} and {3,2,1} are equal, and that is why when handling groups you do not ask about the position of member in a group but just whether the member belongs to group or not.

Every member of the group is counted only once, and therefore the groups {1,2,3,1,1} and {1,2,3} are equal, and of course, the more conventional display is {1,2,3}.

All the operators about groups are based on these main ideas.

Using the code

The main class is Group. The public methods of Group are:

public Group (params string[] group): Constructor.

public void update(params string[] group): Update the group with new one.

public void clear(): Empty the group.

public Group copyto(): Copy the group to another one.

public void print(): Print the members of the class to console

public override string ToString(): Return the members of the group in string.

public int power(): Return the size of the group.

public bool is_empty(): Check whether the group is empty.

public bool is_exist(s): Check whether s exists in the group.

public static Group operator+(Group g, string s): Add member to group.

public static Group operator+(string s, Group g): Add group to member.

public static Group operator+(Group g1,Group g2): A union operator between two groups.

public static Group operator*(Group g1,Group g2): An intersection operator between two groups.

public static Group operator-(Group g, string s): Remove member from group.

public static Group operator-(Group g1, Group g2): Sub one group from another.

public static bool operator<=(Group g1, Group g2): Check whether g1 group is sub group of g2 or equal to g2.

public static bool operator>=(Group g1, Group g2): Check whether g2 group is sub group of g1 or equal to g1.

public static bool operator!=(Group g1, Group g2): Check whether g1 is different from g2.

public static bool operator<(Group g1, Group g2): Check whether g1 is sub group of g2 but does not equal to g2.

public static bool operator>(Group g1, Group g2): Check whether g2 is sub group of g1 but does not equal to g1.

public Group[] P(): Compute all the sub groups of the current group.

The P method to compute the sub groups of a group is using the stack class which is a private class of the Group class and represents a data structure of stack. The public properties and methods of stack are:

public int count: Property to return the size of the stack.

public stack(int sub_group_size): Constructor.

public void push(int val): Push to stack.

public int pop(): Pop from stack.

public int scan(int i): Return the value in position i.

public bool is_empty(): Check whether the stack is empty.

All those methods are simple and trivial, and the code can be found in the source file attached to the document, and that is why I didn’t display the code here except the P method which computes the sub groups of current group.

The P method is complex and took me a long time to write. My first thought at writing this method was to use the recursion way, but then I changed my mind and decided to use stack instead, and I think it was a wise choice.

Here is the code for the P method, and because of its complexity, it is very well documented:

//return all the subgroups of current group
public Group[] P()
{
//hold the sub groups
Group[] temp=new Group[(int)((Math.Pow(2,this.power())-1))];
//hold the positions of the members of each sub group
stack s=new stack(this.power());
int sub_group_size=1; //hold the size of each sub group
int sub_group_counter=0; //hold the index of each sub group
int member_position=0, //hold the value poped up from satck
prev_member_position=-1; //hold the previous value poped up from stack
//loop to control the creation of each group of subgroups
//according to their size
while (sub_group_size<=this.power())
{
//initialize the stack for each size n from 1 ro n
for (int i=1;i<=sub_group_size;i++)
s.push(i);
//the process of building sub groups at each size is continue
//until the stack is empty.
//when the stack is empty it's mean that we finished creating all the
//sub groups of this size.
while (!s.is_empty())
{
temp[sub_group_counter]=new Group();
for (int i=0;i<=s.count-1;i++) //building specific subgroup
temp[sub_group_counter]+=(string)this.group[s.scan(i)-1];
sub_group_counter++;
//after creating each specific sub group we should to drop out
//from stack all the positions that came to end or in a nother word
//finished their job in the most internal loop
do
{
prev_member_position=member_position;
member_position=s.pop();
}
while (member_position>=this.power() ||
prev_member_position==member_position+1);
//if the stack is not empty we should advance the new internal position
//and if necessary also to accomplish new positions instead of the
//positions we droped out
if (member_position!=-1)
{
s.push(++member_position); //advancing the new internal position
//accomplishing the new sub group to the correct size instead
//of the positions we droped out from the stack
for (int i=s.count;i<sub_group_size;i++)
s.push(++member_position);
}
} //end of loop control about the stack emptiness
sub_group_size++;
} //end of loop control about the sub group size
return temp;
}

Here is an example code that demonstrates using the Group class:

using System;
using Groups;
class main
{
staticvoid Main(string[] args)
{
//this program is coming to demonstrate the use of the Group class.
//the input of the program is lists of words.
//the outputs are:
// 1. all the words in each list (every word is displayed only once).
// 2. all the words exist in each list that don't exist in the other lists.
// 3. all the words of all input lists (every word is displayed only once).
// 4. all the common words which exist
// in all the lists(every word is dispayed once).
// 5. the most representing relation between every pair of lists.
int lists_counter;
Group g=new Group();
System.Console.WriteLine();
num_of_lists:
try
{
System.Console.Write("please insert number of lists: ");
lists_counter=int.Parse(System.Console.ReadLine());
}
catch (Exception)
{
goto num_of_lists;
}
Group[] group=new Group[lists_counter];
for (int i=0;i<=lists_counter-1;i++)
{
System.Console.Write("please insert list" +
"of words with space between them: ");
string s=System.Console.ReadLine();
string[] list=s.Split(' ');
group[i]=new Group(list);
}
//printing the members of every group
System.Console.WriteLine();
System.Console.WriteLine("printing the groups");
System.Console.WriteLine("===================");
for (int i=0;i<=group.Length-1;i++)
group[i].print();
System.Console.WriteLine();
//printing the members of every group which not belong to the other groups
g.clear();
System.Console.WriteLine("printing members of each group" +
" that don't belong to other groups");
System.Console.WriteLine("==============================" +
"===================================");
for (int i=0;i<=group.Length-1;i++)
{
g=group[i].copyto();
for (int j=0;j<=group.Length-1;j++)
if (i!=j) g-=group[j];
g.print();
}
System.Console.WriteLine();
//printing the union of all lists
System.Console.WriteLine("printing the union of all lists");
System.Console.WriteLine("===============================");
g.clear();
for (int i=0;i<=group.Length-1;i++)
g+=group[i];
g.print();
System.Console.WriteLine();
//printing the intersection of all lists
System.Console.WriteLine("printing the intersection of all lists");
System.Console.WriteLine("======================================");
g=group[0];
for (int i=1;i<=group.Length-1;i++)
g*=group[i];
g.print();
System.Console.WriteLine();
//printing the relation between each pair of groups
System.Console.WriteLine("printing the relation between each pair of groups");
System.Console.WriteLine("==================================================");
System.Console.WriteLine();
for (int i=0;i<=group.Length-2;i++)
for (int j=i+1;j<=group.Length-1;j++)
if (i!=j)
{
if (group[i]<group[j])
System.Console.WriteLine("{0} < {1}",group[i],group[j]);
elseif (group[i]>group[j])
System.Console.WriteLine("{0} > {1}",group[i],group[j]);
elseif (group[i]==group[j])
System.Console.WriteLine("{0} = {1}",group[i],group[j]);
else
System.Console.WriteLine("{0} <> {1}",group[i],group[j]);
}
System.Console.ReadLine();
}
}

Points of Interest

The most challenging part of the code is the P method. By writing this code, I also learnt how to work with operators overloading, and in this issue, I felt sorry about the absence of the = operator because I noticed it can't be overloaded.

History

26/11/2004 – first version.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Comments and Discussions

I'm relatively new to C#, but what is the structure of the arrays I need to pass into this method?I've tried Double Array, List Array, and nothings seems accept them. I really need to pass in two arrays.Also, which method should I use to measure the delay(if any) between the two arrays I intend to process?

This is a good article, but to call this a group there is something it must enforce. That is that a group is a set such that when you apply a specified operator between any two elements, the result is a member of the set.

So the set of all integers and the + operator forms a group, where any two integers added together form another integer. For the set of integers then, division will not form a group because an integer divided by another integer does not always produce an integer.

this represents a math group of strings.it is very similer to sets in pascal except that sets in pascal representsgroups of enumarations type with limited size like [1..10],[sum,monday,thusday],['a'..'v'] and etc...when my groups contain members of string with no limitation about the size.in matter of operations like union,intersection,existence of member and etc it is the same. about your compare to java stl etc i can't answear because i don't know them.anyway if you look in the example code that demonstrates how to use the classi sure you understand how it works.hope i helped you.good luck.

Hey Yossi,If i am not mistaken the original poster is correct and the english/mathematical name is really "Set" and not "Group" (both are Kvutza in Hebrew). And yes, it's the same as Java/STL etc "Sets"