Working around my Two-Dimensional Array - c#

I just wanna ask what best way to work around a Two-Dimensional Array (2 Columns) which would store: CandidateName and their respective VoteCount.
What I want exactly to do is to, accept an input from the user say: VOTE John 10 wherein John is the name of the candidate and 10 is the votes that he wanna give him. So I need to store {John, 10} into my array. However, after this my program would once again ask the user for votes so if I enter VOTE Doe 15, the entry {Doe, 15} would then be added to the array. If the user enters VOTE John 2, my array needs to be updated and thus the new value would be {John, 12}.
Currently I use two arraylists: CandidateName and VoteCount and I just rely on their index for pairing. However, this isn't really reliable so I'm trying to find another way on how to solve this. However, I'm not really a big fan of multi-dimensional arrays.
Can someone please point me out to a good way on how to achieve this?

public class VoteManager
{
public Dictionary<string, int> Votes { get; private set; }
public VoteManager
{
Votes = new Dctionary<string, int>();
}
public void AddVotes(string name, int voteCount)
{
int oldCount;
if (!Votes.TryGetValue(name, out oldCount))
oldCount = 0;
Votes[name] = oldCount + voteCount;
}

You should use an Associative Array. In the case of C#, such a collection is the Dictionary.
var votes = new Dictionary<string, int>();
votes["John"] = 10;
votes["Bob"] = 20;
votes["John"] = 15; // replaces earlier setting
If you want to add to the exisiting vote, you will need to check if there is an existing value:
private Dictionary<string, int> votesByPeep; // initialized in constructor
private void AddVotes(string peep, int votes)
{
if (this.votesByPeep.ContainsKey(peep)
{
this.votesByPeep[peep] += votes;
}
else
{
this.votesByPeep[peep] = votes;
}
}

Why don't you define a struct/class with two properties, Name and VoteCount. Then you only need one array.
EDIT:
I suggested this because there may be additional operations or properties you want to add to Candidates. If all you need is an association between these two values, a dictionary is the correct solution.

It sounds like a much better solution here is to use a Dictionary<TKey, TValue>. A dictionary / hashtable is ideal for a scenario where you're pairing a value (vote count) with a given key (user name). It makes for very easy update and lookup scenarios
class Container {
private Dictionary<string, int> m_voteMap = new Dictionary<string, int>();
public void SetVote(string user, int votes) {
m_voteMap[user] = votes;
}
public int GetVotes(string user) {
int votes;
if (!m_voteMap.TryGetValue(user, out votes)) {
votes = 0;
}
return votes;
}
}

You can use a dictionary from strings (names) to int (votes), this will give you the {name, votes} pair and a nice quick lookup

Create a class called CandidateVotes, and store that in a List<CandidateVotes> collection.
public class CandidateVotes
{
public string Name {get; set;}
public int Votes {get; set;}
}

Dictionary<string, int> is your friend

This sounds like a good candidate for a Dictionary<T,U>. In this case, Dictionary<string,int>, with the key being the candidate, and the value being the vote count.
// Create dictionary as:
Dictionary<string, int> votes = new Dictionary<string, int>();
You could then make some routines like the following:
void AddVotes(string candidate, int numberOfVotes)
{
if (this.votes.Contains(candidate))
{
// Update the "10 to 12" in your scenario
int current = this.votes[candidate];
current += numberOfVotes;
this.votes[candidate] = current;
}
else
this.votes[candidate] = numberOfVotes; // First time a candidate is used...
}
When you want to list out the votes per candidate, you can do something like:
foreach(var pair in this.votes)
{
Console.WriteLine("Candidate {0} has {1} votes.", pair.Key, pair.Value);
}

Related

Multiple Nested JSON information - C# Process

apologies if I'm doing something wrong, this is my first post.
I'm currently working with C# and want to save a bunch of data out to a JSON file and load it back, but I'm having trouble figuring out how to get it in the following format.
// Primary ID
001
{
// Secondary ID
01
{
// Tertiary ID
01
{
string: "this is some information.",
int: 9371
}
}
// Secondary ID
02
{
// Tertiary ID
01
{
string: "blah blah blah.",
int: 2241
}
}
}
I'd essentially like to be able to call up information with a particular set of IDs for example 001-02-01 which would return a string ("blah blah blah.") and an int (2241).
The reason I want to go about it like this instead of just having one longer ID is so that when the JSON file becomes very large, I'm hoping to be able to speed up the search for information by passing each ID in turn.
If that makes no sense and it would be equally as fast to just pass in one longer ID and not be bothered by this whole nested ID segments concept then please let me know!
If, however what I'm thinking is correct and it would help the speed of finding particular data by structuring it out like this, how would I go about doing that? With nested C# classes in arrays?
The most simple way and efficient way would be to have all data as same type. Currently, you seem to go for each object is of type of the given id:
{
"01":{},
"02" :{}
}
this will not go too well if trying to use a serializable class.
I would recommend the following:
{
"items" : [
{"id":"01" }, { "id":"02" },...
]
}
Then you can serialize/deserialize easily with
[Serializable]
public class Item
{
public string id = null;
}
[Serializable]
public class RootObject
{
public List<Item> items = null;
}
and then in Unity:
void Start(){
string str = GetJson(); // However you get it
RootObject ro = JsonUtility.FromJson<RootObject>(str);
}
if you want to speed up the fetching and your collection is large, convert to dictionary.
Dictionary<string, Item> dict = null;
void Start(){
string str = GetJson(); // However you get it
RootObject ro = JsonUtility.FromJson<RootObject>(str);
this.dict = new Dictionary<string,Item>();
foreach(Item item in ro.items){
Item temp = temp;
this.dict.Add(item.Id, temp);
}
ro = null;
}
Now you can access real fast.
Item GetItem(string id)
{
if(string.IsNullOrEmpty(id) == true){ return null; }
Item item = null;
this.dict.TryGetValue(id, out item);
return item;
}
If you end up storing millions of records in your file and want to start doing something more performant it would be easier to switch to a decent document database like MongoDB rather than trying to reinvent the wheel.
Worry about writing good standard code before worrying about performance problems that don't yet exist.
The following example is not in your language of choice but it does explain that JSON and arrays of 1,000,000 objects can be searched very quickly:
const getIncidentId = () => {
let id = Math.random().toString(36).substr(2, 6).toUpperCase().replace("O", "0")
return `${id.slice(0, 3)}-${id.slice(3)}`
}
console.log("Building array of 1,000,000 objects")
const littleData = Array.from({ length: 1000000 }, (v, k) => k + 1).map(x => ({ cells: { Number: x, Id: getIncidentId() } }))
console.log("Getting list of random Ids for array members [49, 60, 70000, 700000, 999999]")
const randomIds = ([49, 60, 70000, 700000, 999999]).map(i => littleData[i].cells.Id)
console.log(randomIds)
console.log("Finding each array item that contains a nested Id property in the randomIds list.")
const foundItems = littleData.filter(i => randomIds.includes(i.cells.Id))
console.log(foundItems)

How do you store a random key of a dictionary to refresh the dictionary when there are no longer any keys in it?

I am trying to create a dictionary wherein a randomized key is generated, and when I click on a button, this randomized key is subsequently removed from the dictionary and stored in a separate list, so that when there are no longer any keys in the dictionary, as the process has been done X number of times, the dictionary is refreshed.
I'm planning on using this dictionary to further my understanding of using random numbers in unity, practicing it through making a 'simple' quiz dictionary. I have tried creating a separate list and refreshing it (which presumably did not work because I did the code wrong I guess...) and experimenting with creating more variables to control it, which also did not work.
public class textScript : MonoBehaviour
{
public static Dictionary<int, string> questionDict = new Dictionary<int, string>();
public static Dictionary<int, string> answerDict = new Dictionary<int, string>();
public static int randomkey;
public static int removekey;
// You also need to obtain the WRONG values, so you need 'dummy' randomised values
public static int wrongkey;
public static int wrongkey1;
public static int wrongkey2;
public static int wrongkey3;
// You also need to determine the right button
public static int correctbutton;
// In order to obtain question
public static bool nextQuestion;
public void Awake()
{
// Obtains the right dictionaries
questionDict = ES2.LoadDictionary<int, string>(control.question.ToString());
answerDict = ES2.LoadDictionary<int, string>(control.answer.ToString());
}
void Start()
{
nextQuestion = true;
}
void Update()
{
noRepeatAnswers();
randomiseKeys();
GetComponent<TextMeshProUGUI>().text = questionDict[randomkey];
}
void randomiseKeys()
{
if (nextQuestion == true)
{
Random rand = new Random();
for (int i = 0; i < questionDict.Count; i++)
{
randomkey = Random.Range(1, questionDict.Count);
wrongkey = Random.Range(1, questionDict.Count);
wrongkey1 = Random.Range(1, questionDict.Count);
wrongkey2 = Random.Range(1, questionDict.Count);
wrongkey3 = Random.Range(1, questionDict.Count);
}
// Store the above value in a float array
correctbutton = Random.Range(1, 4);
}
followingQuestion();
}
void followingQuestion()
{
nextQuestion = false;
}
The idea is that when you press the 4 buttons ( which use the other integers wrongkey etc.), they will remove this random value (randomkey) from the dictionary before a new question rolls out (through the Boolean), limiting the number of questions until it refreshes, when the value of the keys = null. When I created another list and removed key, the program just went into spasm and crashed.
The purpose of a Dictionary is to store "Keyed" values, literally as KeyValuePair<,>.
From your comments, what you're asking for is a way to group Q&A pairs into categories, then remove those categories. A Dictionary can be useful in that you can name the category, and retrieve a list of Q&A pairs using that name.
public class QandA {
public string Question;
public string Answer;
}
Dictionary<string, List<QandA> > Trivia;
public InitTrivia() {
Trivia = new Dictionary<string, List<QandA>>();
Trivia.Add( "Algebra", new List<QandA> {
new QandA { Question = "What is 2 + 2?", Answer = "Four" },
new QandA { Question = "What is 6 x 3?", Answer = "Eighteen" },
});
}
If you want to randomly select a topic (a random element between zero-inclusive and element count-exclusive):
using System.Linq;
var category = Trivia.Keys.ElementAt(Random.Range(0, Trivia.Keys.Count));
From that topic, randomly select a QandA pair (a random element between zero-inclusive and element count-exclusive):
var qaList = Trivia[category];
var qaInstance = qaList[Random.Range(0, qaList.Count)];
From there you probably want to remove the QandA from the list so it doesn't get re-asked, and remove any empty lists from the dictionary.
When you want to reset, it's probably easiest to just to re-run your original init() code (which will presumably load all the QandA from a save file/serialised source)

Get item of c# dictionary by index?

Im working on a project in unity, im using a dictionary to store player information and then assigning a userID int to the players which is what im attempting to make the index position of the players information in the dictionary, but i think im trying to use this system completely wrong. Currently i have this code:
public class Players : IComparable<Players> {
public int userID;
public string userName;
public int userHealth;
public GameObject userPlayer;
public Players(int newID,string Name,int Health,GameObject player){
userID = newID;
userName = Name;
userHealth = Health;
userPlayer = player;
}
public int CompareTo(Players other){
if(other == null){
return 1;
}
return userID - other.userID;
}
}
to create the Dictionary i use
private Dictionary<NetworkPlayer, Players> playerList = new Dictionary<NetworkPlayer,Players>();
to add to it i use
playerList.Add(player,new Players(playerList.Count,"Test", 100, playerObj));
I was hoping to use the playerList.Count part as a method of indexing it and then sorting it by this index to get the player i wanted back... is there a way of doing this correctly? This is my first time attempting to use dictionarys in c# and im finding it hard to understand how they work, if someone could help lead me to a working method of doing this. All i need to be able to do is to return data based off its index OR using the NetworkPlayer class.
If anyone could help lead me to a working method of doing this id be grateful, Thanks.
A standard dictionary's items are not sorted in this way. Normally, if you want to pull out the player by a specific ID, it would be better to make that the key in the dictionary, ie:
private Dictionary<int, Players> playersByID = new Dictionary<int, Players>();
private Dictionary<NetworkPlayer, Players> playersByNetwork = new Dictionary<NetworkPlayer, Players>();
Note that you could store two dictionaries, one for each form of lookup:
You could then store:
int id = nextID; // Using ID counter...
var newPlayer = new Players(id, "Test", 100, playerObj);
playersById.Add(id, newPlayer);
playersByNetwork.Add(player, newPlayer);
And fetch via:
var player = playersById[120];
Or via:
var player = playersByNetwork[netPlayer];
On a side note: I didn't use the Count as an ID, since that will fail if you ever remove players... If that is something you will never do in your system, you could go back to using the Count property for your next id.
You can also index the dictionary values by yourself enveloping the key-value pair you are interested into a KeyValuePair and associating it with an int like so:
Dictionary<int, KeyValuePair<string, int>> indexedDictionary = new Dictionary<int, KeyValuePair<string, int>>
{
{0, new KeyValuePair<string, int>("my entry", 13) },
{1, new KeyValuePair<string, int>("whatever", 5) },
{............}
};

Value lookup using key or vice versa

First of all, apologies for the nasty title. I will correct it later.
I have some data like below,
"BOULEVARD","BOUL","BOULV", "BLVD"
I need a data structure that is O(1) for looking up any of this words by other. For example, if I use a dictionary I would need to store this keys/values like this, which looks odd to me,
abbr.Add("BLVD", new List<string> { "BOULEVARD","BOUL","BOULV", "BLVD" });
abbr.Add("BOUL", new List<string> { "BOULEVARD", "BOUL", "BOULV", "BLVD" });
abbr.Add("BOULV", new List<string> { "BOULEVARD", "BOUL", "BOULV", "BLVD" });
abbr.Add("BOULEVARD", new List<string> { "BOULEVARD", "BOUL", "BOULV", "BLVD" });
Which data structure to use to keep this data appropriate to my querying terms?
Thanks in advance
Create two HashMap - one maps word to a group number. And the other one maps group number to a list of words. This way you save some memory.
Map<String, Integer> - Word to Group Number
Map<Integer, List<String>> - Group Number to a list of words
You need two O(1) lookups - first to get the group number and then by it - get the list of words.
Assuming abbr is a Dictionary<String, IEnumerable<String>>, you could use the following function:
public static void IndexAbbreviations(IEnumerable<String> abbreviations) {
for (var a in abbreviations)
abbr.Add(a, abbreviations);
}
This will populate the dictionary with the provided list of abbreviations such that when any of them is looked up in the dictionary. It is slightly better than the example code you provided, because I am not creating a new object for each value.
From the documentation, "Retrieving a value by using its key is very fast, close to O(1), because the Dictionary(Of TKey, TValue) class is implemented as a hash table."
The choice of dictionary looks fine to me. As mentioned above, you should use the same list to be referenced in the dictionary. The code could go something like this:
var allAbrList = new List<List<string>>
{
new List<string> {"BOULEVARD", "BOUL", "BOULV", "BLVD"},
new List<string> {"STREET", "ST", "STR"},
// ...
};
var allAbrLookup = new Dictionary<string, List<string>>();
foreach (List<string> list in allAbrList)
{
foreach (string abbr in list)
{
allAbrLookup.Add(abbr, list);
}
}
The last part could be converted into LINQ to have less code, but this way it is easier to understand.
If you don't create a new list for each key, then a Dictionary<string, List<string>> will be fast and reasonably memory-efficient as long as the amount of data isn't enormous. You might also be able to get a little extra benefit from reusing the strings themselves, though the optimizer might take care of that for you anyway.
var abbr = new Dictionary<string, List<string>>;
var values = new List<string> { "BOULEVARD","BOUL","BOULV", "BLVD" };
foreach(var aValue in values) abbr.add(value, values);
As Petar Minchev already said, you can split your list into an list of groups and a list of keys that points to this group. To simplify this (in usage) you can write an own implementation of IDictionary and use the Add method to build those groups. I gave it a try and it seems to work. Here are the important parts of the implementation:
public class GroupedDictionary<T> : IDictionary<T,IList<T>>
{
private Dictionary<T, int> _keys;
private Dictionary<int, IList<T>> _valueGroups;
public GroupedDictionary()
{
_keys = new Dictionary<T, int>();
_valueGroups = new Dictionary<int, IList<T>>();
}
public void Add(KeyValuePair<T, IList<T>> item)
{
Add(item.Key, item.Value);
}
public void Add(T key, IList<T> value)
{
// look if some of the values already exist
int existingGroupKey = -1;
foreach (T v in value)
{
if (_keys.Keys.Contains(v))
{
existingGroupKey = _keys[v];
break;
}
}
if (existingGroupKey == -1)
{
// new group
int newGroupKey = _valueGroups.Count;
_valueGroups.Add(newGroupKey, new List<T>(value));
_valueGroups[newGroupKey].Add(key);
foreach (T v in value)
{
_keys.Add(v, newGroupKey);
}
_keys.Add(key, newGroupKey);
}
else
{
// existing group
_valueGroups[existingGroupKey].Add(key);
// add items that are new
foreach (T v in value)
{
if(!_valueGroups[existingGroupKey].Contains(v))
{
_valueGroups[existingGroupKey].Add(v);
}
}
// add new keys
_keys.Add(key, existingGroupKey);
foreach (T v in value)
{
if (!_keys.Keys.Contains(v))
{
_keys.Add(v, existingGroupKey);
}
}
}
}
public IList<T> this[T key]
{
get { return _valueGroups[_keys[key]]; }
set { throw new NotImplementedException(); }
}
}
The usage could look like this:
var groupedDictionary = new GroupedDictionary<string>();
groupedDictionary.Add("BLVD", new List<string> {"BOUL", "BOULV"}); // after that three keys exist and one list of three items
groupedDictionary.Add("BOULEVARD", new List<string> {"BLVD"}); // now there is a fourth key and the key is added to the existing list instance
var items = groupedDictionary["BOULV"]; // will give you the list with four items
Sure it is a lot of work to implement the whole interface but it will give to an encapsulated class that you don't have to worry about, after it is finished.
I don't see a reason to define the value part of your dictionary as a List<string> object, but perhaps that is your requirement. This answer assumes that you just want to know whether the word essentially means "Boulevard".
I would pick one value as the "official" value and map all of the other values to it, like this:
var abbr = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
abbr.Add("BLVD", "BLVD"); // this line may be optional
abbr.Add("BOUL", "BLVD");
abbr.Add("BOULV", "BLVD");
abbr.Add("BOULEVARD", "BLVD");
Alternatively, you could define an enum for the value part of the dictionary, as shown below:
enum AddressLine1Suffix
{
Road,
Street,
Avenue,
Boulevard,
}
var abbr = new Dictionary<string, AddressLine1Suffix>(StringComparer.CurrentCultureIgnoreCase);
abbr.Add("BLVD", AddressLine1Suffix.Boulevard);
abbr.Add("BOUL", AddressLine1Suffix.Boulevard);
abbr.Add("BOULV", AddressLine1Suffix.Boulevard);
abbr.Add("BOULEVARD", AddressLine1Suffix.Boulevard);

Need a Property to hold the result from a data table

I need to create a property tha will hold to ints for example
int age and int numbers so.. something like This data is comming from a function in another class that returns a DataSet, in the data set there will be those two items like:
Age number
24 1
29 6
32 2
27 1
19 3
So like I said, at the end I would like to have a property that contains this data and can reference at any time from different classes
so I am not sure what to use to hold that data, but it would be something like
public <int, int> personData
{
get
{
return _personData;
}
set
{
_personData = value;
}
}
so I do not know what to use for _personData and for . And how can I access the values of such solution
I would appreciate your help
Looks like a Dictionary<int, int> will do it for you.
Dictionary<int, int> _personalData = new Dictionary<int, int>{ {24, 1}, {29, 6}, ..};
and to access values, you can do
int result = _personalData[24]; // should return 1
public class PersonData
{
public int Age{get;set;}
public int Number {get;set;}
}
You can then create List<PersonData>
And you can access each property like so:
PersonData personData = new PersonData();
personData.Age=12;
personData.Number=10;
You can create a list of PersonData and add items doing this:
List<PersonData> listPersondata = new List<PersonData>();
listPersondata.Add(new PersonData(){Age=12,Number=13});
You can bind this List to any control like a gridview, listbox, etc.

Categories