How to create dictionary within list - c#

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.

Related

How to save List with help of JSON?

everyone!
Tried to make saver of my List with help of combination JSON and PlayerPrefs but stucked with the problem. It don't save my list and don't load. It only giving me my list with zero elements.
Code:
private List<Toggle> _listActiveToggles = new List<Toggle>();
public void Awake()
{
Load();
foreach (Toggle toggle in _listActiveToggles)
{
toggle.isOn = true;
}
}
public void ChooseUsableBuffs(Toggle toggle)
{
int level = PlayerPrefs.GetInt("HDD") / 10;
if (_listActiveToggles.Any(x => toggle))
{
_listActiveToggles.Remove(toggle);
Debug.Log(_listActiveToggles.Count);
return;
}
if (_listActiveToggles.Count >= level)
{
_listActiveToggles[0].isOn = false;
_listActiveToggles.RemoveAt(0);
}
_listActiveToggles.Add(toggle);
Save();
Debug.Log(_listActiveToggles.Count);
}
public void Save()
{
PlayerPrefs.SetString("Key" ,JsonUtility.ToJson(_listActiveToggles));
}
public void Load()
{
_listActiveToggles = JsonUtility.FromJson<List<Toggle>>(PlayerPrefs.GetString("Key"));
}
Tried to check what JSON contains and it showed only: {}
The JsonUtility can not directly serialized array and list types.
You rather need a wrapper class like
[Serializable]
public class ToggleData
{
public List<Toggle> _listActiveToggles = new List<Toggle>();
}
public ToggleData data;
Which now you can serialize
var json = JsonUtility.ToJson(Data);
and deserilialize
JsonUtility.FromJsonOverwrite(json, data);
However, in your specific case I guess it will not work anyway. UnityEngine.UI.Toggle is of type MonoBehaviour and you can not simply deserilialize these from JSON!
You can only store their settings and loading settings into existing toggles.
I guess actually it should be enough to store a list of bool to JSON and iterate over your toggles and the list and do e.g.
using System.Linq;
...
[Serializable]
public class ToggleData
{
public List<bool> ToggleStates = new List<book>();
}
public ToggleData data;
[SerializeField] private List<Toggle> _listActiveToggles = new List<Toggle>();
And then save via
data.ToggleStates = _listActiveToggles.Select(t => t.isOn).ToList();
var json = JsonUtility.ToJson(Data);
and deserilialize via
JsonUtility.FromJsonOverwrite(json, data);
for(var i = 0; i < Mathf.Min(data.ToggleStates.Count, _listActiveToggles.Count); i++)
{
_listActiveToggles[i].isOn = data.ToggleStates[i];
}
Note however that this means you should reference all Toggles you want to save the state for in your list via the Inspector and can not simply remove or add entries on runtime!

Pull values from two different array lists?

I need help on how to make a for loop. Then using the i value as both arrayList index numbers.
My directions say
-Create a loop that uses either the length of the ArrayList or the element to dictate the number of times the loop will run.
-Each time the loop runs, pull another element of the ArrayList and output it in a
meaningful fashion to the console.
static void Main(string[] args)
{
nameArrayLists();
}
public static void nameArrayLists() {
ArrayList teamLists = new ArrayList() {"Cloud 9"};
teamLists.Add("Fnatic");
teamLists.Add("SKT T1");
teamLists.Add("Flash Wolves");
teamLists.Add("EDG");
ArrayList region = new ArrayList() { "North America" };
region.Add("Europe");
region.Add("Korea");
region.Add("Taiwan");
region.Add("China");
So after this, how do I make a for loop using i as both arrayList index numbers? The end result should be like "Fnatic is in the Europe region, cloud 9 is the in north america region" etc.
If i understand correctly, you are looking for something like this:
if (teamLists.Count == region.Count)
{
for (int i = 0; i < teamLists.Count; i++)
{
Console.WriteLine("{0} is in the {1} region", teamLists[i], region[i]);
}
}
else
{
Console.WriteLine("Items in the collections are not matching");
}
Keep in mind: Both the list are in the same order. which means for any i the value at corresponding index should be matching.
There is a best option for you:
Create a simple class with two properties(more if needed), then an overrided ToString() method which is for displaying the text as you described. and then use a List as like the following;
Class definition:
public class TeamNRegion
{
public string TeamName { get; set; }
public string RegionName { get; set; }
public int Id { get; set; }
public override string ToString()
{
return String.Format("{0} is in the {1} region", this.TeamName, this.RegionName);
}
}
Then you can create the list of this class objects like this:
List<TeamNRegion> teamRegionList = new List<TeamNRegion>()
{
new TeamNRegion(){Id=1,TeamName="Fnatic",RegionName="Europe"},
new TeamNRegion(){Id=10,TeamName="SKT T1",RegionName="Korea"},
new TeamNRegion(){Id=11,TeamName="Flash Wolves",RegionName="Taiwan"},
new TeamNRegion(){Id=12,TeamName="EDG",RegionName="China"},
};
// Print the result like this
foreach (TeamNRegion team in teamRegionList)
{
Console.WriteLine(team.ToString());
}

How to add elements in custom Dictionary using 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.

Using Generic Type

I want to use an own function to work with different database tables. As I'm using SQLite, the tables are filled using custom classes.
I'm trying to fill them recursively so I've created this struct and array:
public class cCodesPair
{
public string cCodeKey { get; set; }
public Type CommonCodeClass { get; set; }
public cCodesPair(string key, Type o)
{
this.cCodeKey = key;
this.CommonCodeClass = o;
}
}
private cCodesPair[] codesPairs = new cCodesPair[]
{
new cCodesPair("DESC_UNITS", typeof(SQLEventUnits)),
new cCodesPair("DESC_DISCIPLINE", typeof(SQLDisciplines)),
new cCodesPair("DESC_COUNTRY", typeof(SQLCountries)),
new cCodesPair("DESC_VIDEOS", typeof(SQLVideos)),
new cCodesPair("DESC_ATHLETES", typeof(SQLAthletes))
};
The idea of creating this, was to loop through the array to create query the table and to fill a Dictionary for each.
The function that tries to do that is:
public void Load<T>(T t, SQLiteConnection conn) where T : Type
{
try
{
var query = conn.Table<T>;
//MORE CODE...
} catch (Exception ex)
{
Debug.WriteLine("Exception")
}
}
The function that loops through the array and calls the Load function is the following one:
private async Task fillDictionaries()
{
for (int i = 0; i < codesPairs.Length; i++)
{
MasterDescriptions m = new MasterDescriptions();
Type t = codesPairs[i].CommonCodeClass;
m.Load(t, conn);
}
}
But I get that the table queried has been one called Type.
I would like to get Tables SQLEventUnits, SQLDisciplines, etc dinamically.
Anyone knows how to?
Thanks in advance!
Do you know Microsoft Enterprise Library?
https://msdn.microsoft.com/en-us/library/ff648951.aspx
Does exactly what you want to implement.
Another reference:
http://www.codeproject.com/Tips/657233/Enterprise-Library-6-Sqlite-Logging-and-Exceptions

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