How to add elements in custom Dictionary using C#? - c#

I have a dictionary for clustering purpose in a class named Cluster in C# as:
Dictionary<int, List<ClusterMember>>
whereas int represent the cluster id, List<ClusterMember>> represent the members in that cluster id and ClusterMember is another class. I have shown here the whole code structure as:
public class ClusterMember
{
public string _name { get; set; }
}
public class Cluster
{
public Dictionary<int, List<ClusterMember>> _dic { get; set; }
public Cluster(int _id, List<ClusterMember> _clusMem)
{
_dic.Add(_id, _clusMem);
}
}
whereas I have used these classes in this method as:
public static List<Cluster> DP_Cluster(List<string> _customer, double _alpha)
{
var _currentClusters = 0; // current number of clusters i.e. "k"
var _memberNumber = 0; // running member number i.e. "n"
//var _dic = new Dictionary<int, List<string>>();
var _probOld = 0.0;
var _probNew = 0.0;
List<Cluster> _myClusters = new List<Cluster>();
//Cluster _cluster = new Cluster(?);
// How to Add cluster using above classes
// How to Add cluster Member using above classes
_myClusters.Add(_cluster);
//_dic.Add(_currentClusters, _customer.ElementAt(_memberNumber));
_currentClusters += 1;
for(int _i = 1; _i < _customer.Count - 1; _i++)
{
if( _i <= _currentClusters)
{
_probOld = myClusters[_i].Members.Count / ((_i+1) - 1 + _alpha);
}
else
{
_probNew = _alpha / ((_i+1) - 1 + _alpha);
}
if(_probNew > _probOld)
{
// Add _customer.ElementAt(_memberNumber+=1) to New Cluster
Cluster cluster = new Cluster( _currentClusters += 1 );
myClusters.Add(cluster);
}
else
{
// Add _customer.ElementAt(_memberNumber+=1) to Old Cluster
}
}
return myClusters;
}
Now how do I Add in _dic object of Dictionary while in for loop? Moreover I may have to add more than one cluster members to same _id more than once as
I may add a cluster member to _id = 1 in an iteration,
then have to add a cluster member to an _id = 2 in another
iteration,
then it may turn to add another cluster member to same id i.e. _id = 1 and vice versa.
Moreover, it'll be more meaningful to me if it is possible to start cluster id with 1 (not 0as of default _dic index).

Moreover I may have to add more than one cluster members to same id
more than once
You can check for the key for each loop iteration like that:
public void AddInCluster(int id, List<ClusterMember> _clusMem)
{
if (_dic.ContainsKey(id))
{
foreach (var clusterMember in _clusMem)
{
_dic[id].Add(clusterMember);
}
}
else
{
_dic.Add(id, _clusMem);
}
}
Or you can use the TryGetValue from Dictionary:
public void AddInCluster(int id, List<ClusterMember> _clusMem)
{
List<ClusterMember> members;
if (_dic.TryGetValue(id, out members))
{
foreach (var clusterMember in _clusMem)
{
members.Add(clusterMember);
}
}
else
{
_dic.Add(id, _clusMem);
}
}
Moreover, it'll be more meaningful to me if it is possible to start
cluster id with 1
What about wrapping your int into a ClusterId class which could raise exception if an id is 0?
Also your Cluster class could override the accessor operator [] on the dictionary to give a meaningful abstraction in your context (starting from 1 instead of 0 for example)
You may also add a Get working like your Add to check if this id exists:
public List<ClusterMember> GetFromCluster(ClusterId id)
{
if (_dic.ContainsKey(id))
{
return _dic[id];
}
throw new ClusterDoesNotContainsThisId(id);
}

How about using the Add method for Dictionaries? like:
if(needToAddNewCluster){
_dic.Add(index, new List<ClusterMember>());
}
if(needToExtendCluster){
_dic[index].Add(clusMem);
}
in this i assume that needToAddNewCluster checks that _dic.ContainsKey(index).

You can add method to your Cluster class
public void AddToCluster(int id, ClusterMember member)
{
// checks if cluster with specific id is already in Dictionary
if(!_dic.ContainsKey(id))
_dic.Add(id,new List<ClusterMember>());
_dic[id].Add(member);
}
You can use it in iteration like this
int id = 1; // cluster id
foreach(var m in members)
{
// adding members to cluster with id = 1
cluster.AddToCluster(id,m);
}
UPDATE
also can we get list count for each cluster id i.e. cluster members count for each cluster id?
You can add these two methods
// get members count for specific cluster id
public int GetCount(int id)
{
return _dict[id].Count;
}
// get members count for all clusters
public Dictionary<int,int> GetCounts()
{
return _dict.ToDictionary(k=>k.Key,v=>v.Value.Count);
}
Which you can access like this
var counts = cluster.GetCounts();
var c1Cnt=counts[1]; // 1 is cluster id

I would change the implementation of the Culster class slightly. The _dic should be a getter only property with an initializer. According to the usual .NET C# naming conventions, properties should be in PascalCase, therefore I renamed it to Dic. (A better name would be MemberDictionary or Members). Underlined _camelCase identifiers are usually used for fields. Method parameters and local variables have camelCase.
Then add new methods for adding one or several members. Both methods first check to see whether the list is already there. If it's there new members are added to the list, otherwise a new list is created initialized with the new members and then added to the dictionary.
public class Cluster
{
public Dictionary<int, List<ClusterMember>> Dic { get; }
= new Dictionary<int, List<ClusterMember>>();
// Initialize empty cluster.
public Cluster()
{
}
// Initialize cluster with one initial member.
public Cluster(int key, ClusterMember member)
{
Add(key, member);
}
// Initialize cluster with many members.
public Cluster(int key, IEnumerable<ClusterMember> members)
{
Add(key, members);
}
// Allows you to a one new member.
public void Add(int key, ClusterMember member)
{
if (Dic.TryGetValue(key, out var memberList)) {
memberList.Add(member);
} else {
memberList = new List<ClusterMember> { member };
Dic.Add(key, memberList);
}
}
// Allows you to add many members.
public void Add(int key, IEnumerable<ClusterMember> members)
{
if (Dic.TryGetValue(key, out var memberList)) {
memberList.AddRange(members);
} else {
memberList = new List<ClusterMember>(members);
Dic.Add(key, memberList);
}
}
}
This implementation delegates the dictionary and list creation and the details of adding members to the Cluster class.
Btw.: Dictionaries work with a key, not an index.
I don't know where you are getting the member number from, nor do I understand your clustering algorithm; however, I think that with these changes DP_Cluster could look like this:
public static List<Cluster> DP_Cluster(List<string> customers, double alpha)
{
double probOld = 0.0;
double probNew = 0.0;
var clusters = new List<Cluster>();
Cluster currentCluster = null;
for (int i = 0; i < customers.Count; i++) {
if (i <= clusters.Count) {
probOld = clusters[i].Dic.Count / (i + alpha);
} else {
probNew = alpha / (i + alpha);
}
if (probNew > probOld || currentCluster == null) {
currentCluster = new Cluster();
clusters.Add(currentCluster);
}
currentCluster.Add(_memberNumber, new ClusterMember { Name = customers[i] });
}
return clusters;
}
Some of the constructors and methods in Cluster could prove superfluous eventually, as we are always adding one single customer at a time.

Related

How to create dictionary within list

I have a class Mobile in which my dictionary is declared. I have another class Cell through which I want to call this dictionary and add items into it. I have created a function in the Mobile class to add elements into the dictionary. My two classes are.
public class Mobile {
public Dictionary<string, Mobile> dict;
public Mobile(int x,int y) {
this.x=x;
this.y=y;
dict = new Dictionary<string, Mobile>();
}
pulic void Add_data_to_dictionary(string a,Mobile b)
{
this.dict.Add(a,b);
}
}
public class Cell
{
Mobile x=new Mobile():
}
I need to implement my code in Cell class. My problem is that I have to create a list of nodes of class Mobile where each node must contain a dictionary and each dictionary should have multiple key-value pairs.
Hierarchy is like this
node1->dictionary[key1,val1,key2,val2]
node2->dictionary[key1,val1,key2,val2]
node3->dictionary[key1,val1,key2,val2]
can anyone help me how do I do that?
I'm still not sure what you trying to achieve, but as you said:
I need a List of class Mobile. At each index of List, I need One
Dictionary of class Mobile where each dictionary can have many entries
of key,value pairs.
It could be done probably in that way:
class Program
{
static void Main(string[] args)
{
// Initialize List of your Mobiles
List<Mobile> mobiles = new List<Mobile>();
// Fill list in some way
for (int i = 0; i < 5; i++)
{
// Create new Mobile
Mobile mobile = new Mobile();
// Add data to its Dictionary
mobile.AddDataToDictionary("SomeKey #" + i, mobile); // Add itself as value?!
// Add to list of Mobiles (your nodes)
mobiles.Add(mobile);
}
// Create Cell instance and pass list of Mobiles to it
Cell cell = new Cell(mobiles);
// Do what you want with mobiles there
cell.DoWorkWithMobiles();
Console.ReadKey();
}
}
public class Mobile
{
// Make Dictionary as public property to grant access to it for read purposes
public Dictionary<string, Mobile> Dict { get; private set; }
// I removed arguments x/y for this example
public Mobile()
{
Dict = new Dictionary<string, Mobile>();
}
public void AddDataToDictionary(string key, Mobile value)
{
Dict.Add(key, value);
}
}
public class Cell
{
// To store list, which was passed to class constructor
private List<Mobile> mobiles;
public Cell(List<Mobile> mobiles)
{
this.mobiles = mobiles;
}
public void DoWorkWithMobiles()
{
// Very unclear what to do here
for (int i = 0; i < mobiles.Count; i++)
{
Mobile mobile = mobiles[i];
Mobile mobileFromDict = mobile.Dict["SomeKey #" + i];
//or
mobile.Dict.TryGetValue("SomeKey #" + i, out Mobile mob);
Mobile m = mob.Dict["SomeKey #" + i];
}
}
}
As you can see, an architecture and logic of your project isn't clear and example may be incorrect and stupid.

rearrange a list of objects by type field in C#

I have an incoming list of alerts and I use a MapFunction as:
private static BPAlerts MapToAlerts(List<IntakeAlert> intakeAlerts)
{
// Make sure that there are alerts
if (intakeAlerts.IsNullOrEmpty()) return new BPAlerts { AllAlerts = new List<BPAlert>(), OverviewAlerts = new List<BPAlert>() };
// All Alerts
var alerts = new BPAlerts
{
AllAlerts = intakeAlerts.Select(
alert => new BPAlert
{
AlertTypeId = alert.AlertTypeId ?? 8100,
IsOverview = alert.IsOverviewAlert.GetValueOrDefault(),
Text = alert.AlertText,
Title = alert.AlertTitle,
Type = alert.AlertTypeId == 8106 ? "warning" : "report",
Severity = alert.AlertSeverity.GetValueOrDefault(),
Position = alert.Position.GetValueOrDefault()
}).OrderBy(a => a.Position).ToList()
};
// Alerts displayed on the overview page
alerts.OverviewAlerts =
alerts.AllAlerts
.ToList()
.Where(a => a.IsOverview && !string.IsNullOrEmpty(a.Title))
.Take(3)
.ToList();
return alerts;
}
the BPAlerts type contains list of two type:
public class BPAlerts
{
public List<BPAlert> AllAlerts { get; set; }
public List<BPAlert> OverviewAlerts { get; set; }
}
And the BPAlert type is defined as:
public class BPAlert
{
public short AlertTypeId { get; set; }
public string Type { get; set; }
public int Severity { get; set; }
public bool IsOverview { get; set; }
public string Title { get; set; }
public string Text { get; set; }
public int Position { get; set; }
public string Id { get; internal set; } = Guid.NewGuid().ToString();
}
I want to achieve a task in which the MaptoAlerts function returns a alerts object with overviewalerts which are sorted based on the type of BPAlert. To be more clear in the following order if present:
Confirmed Out of Business - 8106 \n
Bankruptcy - 8105 \n
Lack of Licensing - 8111 \n
Investigations - 8109 \n
Government Actions - 8103 \n
Pattern of Complaints - 8104 \n
Customer Reviews - 8112 \n
Accreditation - 8110 \n
Misuse of BBB Name - 8101 \n
Advisory - 8107 \n
Advertising Review – 8102 \n
Solution #1 Order values array
I would just define the order of those ids in some kind of collection, can be an array:
var orderArray = new int[]
{
8106, // Confirmed Out of Busine
8105, // Bankruptcy
8111, // Lack of Licensing
8109, // Investigations
8103, // Government Actions
8104, // Pattern of Complaints
8112, // Customer Reviews
8110, // Accreditation
8101, // Misuse of BBB Name
8107, // Advisory
8102, // Advertising Review
};
Then iterate through array while incrementing order value. While looping check if order array contains actual type id which order value I'm trying to evaluate:
for (int orderValue = 0; orderValue < orderArray.Length; orderValue++)
{
if (alertTypeId == orderArray[orderValue])
{
return orderValue;
}
}
If not found in the array, return highest value possible:
return int.MaxValue
Whole method would look like this and it would evaluate the order for alert type id:
public int GetAlertTypeIdOrder(short alertTypeId)
{
var orderArray = new int[]
{
8106, // Confirmed Out of Busine
8105, // Bankruptcy
8111, // Lack of Licensing
8109, // Investigations
8103, // Government Actions
8104, // Pattern of Complaints
8112, // Customer Reviews
8110, // Accreditation
8101, // Misuse of BBB Name
8107, // Advisory
8102, // Advertising Review
};
for (int orderValue = 0; orderValue < orderArray.Length; orderValue++)
{
if (alertTypeId == orderArray[orderValue])
{
return orderValue;
}
}
return int.MaxValue;
}
Usage:
var sortedAlerts = alerts
.AllAlerts
.OrderByDescending(a => GetAlertTypeIdOrder(a.AlertTypeId))
.ToList();
It also works in a descending way.
Solution #2 Order values dictionary
You could achieve better performance by reducing the redundancy - repeated creation of array storing order values. Better idea would be to store the order rules in a dictionary. I know that code below creates an array too, but the concept is that it would be called once to get the dictionary which would be then passed over.
public Dictionary<int, int> GetOrderRules()
{
var alertTypeIds = new int[]
{
8106, // Confirmed Out of Busine
8105, // Bankruptcy
8111, // Lack of Licensing
8109, // Investigations
8103, // Government Actions
8104, // Pattern of Complaints
8112, // Customer Reviews
8110, // Accreditation
8101, // Misuse of BBB Name
8107, // Advisory
8102, // Advertising Review
};
var orderRules = new Dictionary<int, int>();
for (int orderValue = 0; orderValue < alertTypeIds.Length; orderValue++)
{
orderRules.Add(alertTypeIds[orderValue], orderValue);
}
return orderRules;
}
So the GetAlertIdOrder() method would look different, but still keeping the idea from previous solution:
public int GetAlertIdOrder(short alertTypeId, IDictionary<int, int> orderRules)
{
if (orderRules.TryGetValue(alertTypeId, out int orderValue))
{
return orderValue;
}
else
{
return int.MaxValue;
}
}
Usage:
var orderRules = GetOrderRules();
var sortedAlerts = alerts
.AllAlerts
.OrderBy(a => GetAlertIdOrder(a.AlertTypeId, orderRules))
.ToList();
(a) I wouldn't mix sorting with the mapper. let the mapper just do its thing. (this is separation of concerns ) .. aka, no ordering/sorting. IMHO, you'll always end up with way too much voodoo in the mapper that is hard to understand. You're already on this path with the above code.
(b) if "OverviewAlerts" is a subset of AllAlerts (aka, AllAlerts is the superset), then hydrate AllAlerts, and create a read-only "get" property where you filter AllAlerts to your subset by its rules. optionally, consider a AllAlertsSorted get property. this way, you allow your consumers to choose if they want raw or sorted...since there is a cost with sorting.
public class BPAlerts
{
public List<BPAlert> AllAlerts { get; set; }
public List<BPAlert> OverviewAlerts {
get
{
return null == this.AllAlerts ? null : this.AllAlerts.Where (do you filtering and maybe sorting here ) ;
}
}
}
public List<BPAlert> AllAlertsSorted{
get
{
return null == this.AllAlerts ? null : this.AllAlerts.Sort(do you filtering and maybe sorting here ) ;
}
}
}
if you do the read-only properties, then you have more simple linq operations like
OrderBy(x => x.PropertyAbc).ThenByDescending(x => x.PropertyDef);
99% of my mapping code looks like this. I don't even throw an error if you give null input, i just return null.
public static class MyObjectMapper {
public static ICollection < MyOtherObject > ConvertToMyOtherObject(ICollection <MyObjectMapper> inputItems) {
ICollection <MyOtherObject> returnItems = null;
if (null != inputItems) {
returnItems = new List <MyOtherObject> ();
foreach(MyObjectMapper inputItem in inputItems) {
MyOtherObject moo = new MyOtherObject();
/* map here */
returnItems.Add(moo);
}
}
return returnItems;
}
}

Assert Equal two list of objects UnitTesting c#

I'm currently doing some unit testing of a copy function and I need to compare the elements of the objects between the old list, and the newly copied list.
It works fine, but I was wondering if I can do it in a way that doesn't involve a for loop.
Here is my object:
new NaturePointObject
{
SId = 1,
Name = "Test",
Category = NaturePointCategory.Category1,
CreatorType = CreatorTypeEnum.1,
NaturR = NaturR.Bn,
Description = "Test",
Kumulation = Kumulation.EnEjendom,
Id = 1
}
My old list contains "NaturePointObject" and is called naturPointList, and it will be copied to a list called newNaturePointList.
Here is how I Assert to know if it copied succesfully:
Assert.AreEqual(naturPointList.Count,newNaturePointList.Count);
for (var i = 0; i < newNatureList.Count; i++)
{
Assert.AreEqual(naturPointList[i].Category, newNaturePointList[i].Category);
Assert.AreEqual(naturPointList[i].Description, newNaturePointList[i].Description);
Assert.AreEqual(naturPointList[i].Kumulation, newNaturePointList[i].Kumulation);
Assert.AreEqual(naturPointList[i].Name, newNaturePointList[i].Name);
Assert.AreEqual(naturPointList[i].CreatorType, newNaturePointList[i].CreatorType);
Assert.AreEqual(naturPointList[i].NaturR, newNaturePointList[i].NaturR);
Assert.AreNotEqual(naturPointList[i].SId, newNaturePointList[i].SId);
}
As you can see not all elements of the object must be equal. And I don't care about the "Id" of the object.
Is there a shorter way to do this, than run a for loop?
Probably you want to use CollectionAssert:
CollectionAssert.AreEqual(naturPointList, newNaturePointList, NaturePointObject.CategoryCreatorTypeComparer);
The only thing you need to take in mind is that you need to implement IComparer, to use in the Assert method:
public class NaturePointObject
{
private static readonly Comparer<NaturePointObject> CategoryCreatorTypeComparerInstance = new CategoryCreatorTypeRelationalComparer();
private sealed class CategoryCreatorTypeRelationalComparer : Comparer<NaturePointObject>
{
public override int Compare(NaturePointObject x, NaturePointObject y)
{
// compare fields which makes sense
if (ReferenceEquals(x, y)) return 0;
if (ReferenceEquals(null, y)) return 1;
if (ReferenceEquals(null, x)) return -1;
var categoryComparison = string.Compare(x.Category, y.Category, StringComparison.Ordinal);
if (categoryComparison != 0) return categoryComparison;
return string.Compare(x.CreatorType, y.CreatorType, StringComparison.Ordinal);
}
}
public static Comparer<NaturePointObject> CategoryCreatorTypeComparer
{
get
{
return CategoryCreatorTypeComparerInstance;
}
}
public int SId { get; set; }
public string Category { get; set; }
//other properties
public string CreatorType { get; set; }
}
You can try
Assert.IsTrue(naturPointList.SequenceEqual(newNaturePointList));
If you want to ignore the Id, you can create other classes (without Ids).
Later edit: you could overwrite the Equals method and ignore the Id.

c#: collections with unique elements

Is there a collection in C# that guarantees me that I will have only unique elements? I've read about HashSet, but this collection can contain duplicates. Here is my code:
public class Bean
{
public string Name { get; set; }
public int Id { get; set; }
public override bool Equals(object obj)
{
var bean = obj as Bean;
if (bean == null)
{
return false;
}
return this.Name.Equals(bean.Name) && this.Id == bean.Id;
}
public override int GetHashCode()
{
return Name.GetHashCode() * this.Id.GetHashCode();
}
}
You may complain about using non-readonly properties in my GetHashCode method, but this is a way of doing (not the right one).
HashSet<Bean> set = new HashSet<Bean>();
Bean b1 = new Bean {Name = "n", Id = 1};
Bean b2 = new Bean {Name = "n", Id = 2};
set.Add(b1);
set.Add(b2);
b2.Id = 1;
var elements = set.ToList();
var elem1 = elements[0];
var elem2 = elements[1];
if (elem1.Equals(elem2))
{
Console.WriteLine("elements are equal");
}
And in this case, my set contains duplicates.
So is there a collection in C# that guarantees me that it does not contains duplicates?
So is there a collection in C# that guarantees me that it does not
contains duplicates?
There is no existing collection class in C# that does this. You could write your own, but there is no existing one.
Some extra information regarding the issue you are experiencing
If you change a HashSet entry after adding it to the HashSet, then you need to regenerate the HashSet. My below RegenerateHashSet can be used to do that.
The reason you need to regenerate is that duplicate detection only occurs at insertion time (or, in other words, it relies on you not changing an object after you insert it). Which makes sense, if you think about it. The HashSet has no way to detect that an object it contains has changed.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Test
{
public static class HashSetExtensions
{
public static HashSet<T> RegenerateHashSet<T>(this HashSet<T> original)
{
return new HashSet<T>(original, original.Comparer);
}
}
public class Bean
{
public string Name { get; set; }
public int Id { get; set; }
public override bool Equals(object obj)
{
var bean = obj as Bean;
if (bean == null)
{
return false;
}
return Name.Equals(bean.Name) && Id == bean.Id;
}
public override int GetHashCode()
{
return Name.GetHashCode() * Id.GetHashCode();
}
}
public class Program
{
static void Main(string[] args)
{
HashSet<Bean> set = new HashSet<Bean>();
Bean b1 = new Bean { Name = "n", Id = 1 };
Bean b2 = new Bean { Name = "n", Id = 2 };
set.Add(b1);
set.Add(b2);
b2.Id = 1;
var elements = set.ToList();
var elem1 = elements[0];
var elem2 = elements[1];
if (elem1.Equals(elem2))
{
Console.WriteLine("elements are equal");
}
Console.WriteLine(set.Count);
set = set.RegenerateHashSet();
Console.WriteLine(set.Count);
Console.ReadLine();
}
}
}
Note that the above technique is not bullet-proof - if you add two objects (Object A and Object B) which are duplicates and then change Object B to be different to Object A then the HashSet will still only have one entry in it (since Object B was never added). As such, what you probably want to do is actually store your complete list in a List instead, and then use new HashSet<T>(yourList) whenever you want unique entries. The below class may assist you if you decide to go down that route.
public class RecalculatingHashSet<T>
{
private List<T> originalValues = new List<T>();
public HashSet<T> GetUnique()
{
return new HashSet<T>(originalValues);
}
public void Add(T item)
{
originalValues.Add(item);
}
}
If you don't write your own collection type and handle property changed events to re-evaluate the items, you need to re-evaluate the items at each access. This can be accomplished with LINQ deferred execution:
ICollection<Bean> items= new List<Bean>();
IEnumerable<Bean> reader = items.Distinct();
Rule: only use items to insert or remove elements, use reader for any read access.
Bean b1 = new Bean { Name = "n", Id = 1 };
Bean b2 = new Bean { Name = "n", Id = 2 };
items.Add(b1);
items.Add(b2);
b2.Id = 1;
var elements = reader.ToList();
var elem1 = elements[0];
var elem2 = elements[1]; // throws exception because there is only one element in the result list.

Creating list/array of class instances?

I'm fairly new to C# and I have just learned about creating custom classes. The problem is, I can't figure out how to take the 40~65 instances of this class and put them in a list/array (whichever one I need) where I can locate and choose one based on an attribute defined in it.
Here's the class I have created right now:
public class Team
{
protected int teamNum;
protected double averageMatchPoints;
protected string location;
protected int matchesPlayed;
protected int matchesPending;
protected int blowouts;
//Team Number
public void SetNumber(int num)
{
teamNum = num;
}
public int GetNumber()
{
return teamNum;
}
//Average Points per match
public void AverageMatchPoints(double p)
{
averageMatchPoints = p;
}
public double GetAverageMatchPoints()
{
return averageMatchPoints;
}
//location information
public void SetLocation(string l)
{
location = l;
}
public string GetLocation()
{
return location;
}
//Number of Played Matches
public void PlayedMatches(int mat)
{
matchesPlayed = mat;
}
public int GetPlayedMatches()
{
return matchesPlayed;
}
//Number of matches pending (not played)
public void PendingMatches(int pen)
{
matchesPending = pen;
}
public int GetPendingMatches()
{
return matchesPending;
}
//Number of Blowouts (matches where the robot was disbaled for any number of reasons)
public void SetBlowouts(int b)
{
blowouts = b;
}
public int GetBlowouts()
{
return blowouts;
}
}
Now, if I had 40~65 of these teams competing at an event and I made an instance of this class for each one, how would I populate a combobox with each team number (teamNum) and then locate one specific team out of all the instances in the program by their team numbers?
I recommend a dictionary!
// Declared somewhere
private Dictionary<int, Team> _teamDictionary = new Dictionary<int, Team>();
.
.
.
//Initialization code - I assume you have gotten your teams from a database or somewhere?
foreach (var team in myTeamsList)
{
_teamDictionary.Add(team.teamNum, team);
}
.
.
.
// Later when you want to locate a team:
var team = _teamDictionary[selectedTeamNum];
Have you tried creating a List yet?
List<Team> Teams { get; set; }
You can then bind your combobox to the list/collection/IEnumerable of all the teams that you have. To initialize the teams up to 40/60 do the following?
for(int i = 0; i < 60; i++)
{
Team t = new Team();
t.Name = "Team 1";
t.TeamNumber = i + 1;
Teams.Add(t);
}
List<Team> allTheTeams = new List<Team>();
for(var i = 0; i < 65; i++){
allTheTeams.Add(new Team { teamNum = i });
}
And to get the team with number 34:
allTheTeams.FirstOrDefault(x => x.teamNum == 34);
Like this:
Add a constructor to your class that takes the teamnumber:
(this is the best solution if every team needs to have a number. So you can not forget to set the team number as you can not create an object of type team without setting the number in the constructor)
public class Team
{
protected int _teamNum;
public Team(int teamNum)
{
_teamNum = teamNum;
}
public int getTeamNum()
{
return _teamNum;
}
//more logic
}
Populate a dictionary, the comboBox and get a team for its number:
Dictionary<int, Team> dictionary = new Dictionary<int, Team>();
int teamNum = 1;
// Add your Teams to a dictionary (example)
dictionary.Add(teamNum ,new Team(teamNum++));
dictionary.Add(teamNum, new Team(teamNum++));
dictionary.Add(teamNum, new Team(teamNum++));
// Populate a comboBox
foreach(KeyValuePair<int,Team> kvp in dictionary)
{
comboBox1.Items.Add(kvp.Value.getTeamNum().ToString());
}
// get a team for a given teamNumer
int targetTeamNumber = 2;
if (dictionary.ContainsKey(targetTeamNumber))
{
Team team = dictionary[targetTeamNumber];
// do something with the team
}

Categories