Array of dictionaries with Unity and Firebase database - Get values from key - c#

First of all - I am pretty new to Unity.
I am trying to retrieve some data from my firebase database, store the data in an array/list of dictionaries, and then use the array/list to show the data from my server.
So... My way of trying to do:
1: Create array of dictionaries to hold my data:
[System.Serializable]
public class Global
{
public static Dictionary<string, object>[] offers;
}
2: Handle the data from the database, and store it in the array:
void Handle_ChildAdded(object sender, ChildChangedEventArgs e)
{
if (e.DatabaseError != null)
{
Debug.LogError(e.DatabaseError.Message);
return;
}
// Do something with the data in args.Snapshot
if (e.Snapshot.Value != null)
{
var dict = e.Snapshot.Value as Dictionary<string, object>;
if (dict != null)
{
Debug.Log(dict);
Global.offers = new Dictionary<string, object>[Global.storesCount+1];
Global.offers[Global.storesCount] = dict;
Global.storesCount++;
hasHaded = true;
}
}
}
So now I have alle the snapshots from my database in my Global.offers array. The struckture of the snapshot i should get look something likes this:
Time to show the data from my array
Everything works fine until this point - Because now I need to show the data I just stored in my Global.offers array.
I try to do that with a loop. I loop though the array and search for the keys from my database and Instantiate the data inside a prefab of a gameobject like this:
for (int i = 0; i < Global.storesCount; i++)
{
Transform scrollViewObj = Instantiate(prefab, new Vector3(0, (downSize * i) - firstY, 0), Quaternion.identity);
scrollViewObj.transform.SetParent(scrollContent.transform, false);
scrollViewObj.transform.Find("Overskift").gameObject.GetComponent<Text>().text = Global.offers[i]["Store"] as string;
scrollViewObj.transform.Find("Text (1)").gameObject.GetComponent<Text>().text = Global.offers[i]["Headline"] as string;
scrollViewObj.transform.Find("Text (2)").gameObject.GetComponent<Text>().text = "Din pris: " + Global.offers[i]["Price"] as string + " kr.";
scrollViewObj.transform.Find("Text (3)").gameObject.GetComponent<Text>().text = "Spar: " + Global.offers[i]["AndresPris"] as string + " kr.";
}
This is where I get the trouble. For some reason Global.offers[i]["Store"] as string == null, witch of course means that I can't instantiate the object. I get this error:
NullReferenceException: Object reference not set to an instance of an object
LoadOffers.Start () (at Assets/Scripts/LoadOffers.cs:36)
It is so weird, because when I try to debug I get some conflicting results:
The length of the array is 19. So it is not empty.
When I try to Debug.Log the array out I get:
System.Collections.Generic.Dictionary`2[System.String,System.Object][]
But when I search for values with keys like:
Debug.Log(Global.offers[0]["Store"]);
All I get is null. Am I searching wrong after the values? Or can anyone else see what I am doing wrong?

The Problem
Your main problem is that Global.offers
is an array and therefore has a fixed length and can not be enlarged dynamically that simple (you would have to copy the array everytime!)
You kind of tried to solve this in Handle_ChildAdded but in the line
Global.offers = new Dictionary<string, object>[Global.storesCount+1];
what you actually do is creating a new empty(!) array of dictionaries with length Global.storeCount+1. You don't copy the current values to a new array.
so after all executions what you get is an array with only null. Only the last item of the array will have the content coming from
Global.offers[Global.storeCount] = dict;
so only the last value will actually be set. It looks somewhat like
{null, null, null, null, ..., Dictionary<string, object> }
that's why the length is a correct value. Your exception is actually already thrown the moment you try to access
Global.offers[0]
which is null.
Solution
I would recommend not to use an array at all but instead a List which in contrary to the array can grow dynamically
[System.Serializable]
public class Global
{
public static List<Dictionary<string, object>> offers = new List<Dictionary<string, object>>();
}
and than before starting to fill the list by adding all dictionaries you should actually somwhere call
Global.offers.Clear();
to reset the list otherwise it keeps growing bigger and bigger with every loading of the database. Also if you are absolutely sure you call this only once you might not need this I would always recommend to do it in order to have a clean, in general working solution.
And later add your elements in
void Handle_ChildAdded(object sender, ChildChangedEventArgs e)
{
if (e.DatabaseError != null)
{
Debug.LogError(e.DatabaseError.Message);
return;
}
// Do something with the data in args.Snapshot
if (e.Snapshot.Value != null)
{
var dict = e.Snapshot.Value as Dictionary<string, object>;
if (dict != null)
{
Debug.Log(dict);
Global.offers.Add(dict);
hasHaded = true;
}
}
}
Later you do access elements in a List the same way as in an array
Debug.Log(Global.offers[0]["Store"]);
Note that you also don't need the variable storeCount neither in your solution - you could have simply used
Global.offers.Length
nor in this new solution - you can simply use
Global.offers.Count

Related

Initialize Array of Dictionary Randomly

I am dealing with Array of Dictionaries and this SO Post is really helpful to achieve what I want so far.
But, now I want to initialize Dictionary for an array index based on the output of code.
I have a Dictionary<int,string>, where I am storing a Id as Key. I am having Array of 10 dictionaries as follows:
Dictionary<int, string>[] matrix = new Dictionary<int, string>[10];
So, based on the value of (Id%10), i want to store that record in a respective array. For i.e., if id= 12, I want to store it in matrix[2]. If id = 15, i want to store it in matrix[5].
Now,question is, how to check each time whether a dictionary is initialized for a particular index or not. If yes, than add the record to the dictionary else initialize the instance and then add the record to Dictionary.
Something like following:
if {} // if dict with id%10 is initialized then
{
matrix[id%10].Add();
}
else
{
matrix[id%10] = new Dictionary<int,string>();
matrix[id%10].Add();
}
Edit: I know i can initialize all first using loop, but I want to initialize only when it's necessary.
Dictionary<int, string>[] matrix = new Dictionary<int, string>[10];
int id = 0; // Number here
int index = id % 10;
if (matrix[index] == null)
{
matrix[index] = new Dictionary<int, string>();
}
int key = 0; // key you want to insert
if (matrix[index].ContainsKey(key))
{
// Dictionary already has this key. handle this the way you want
}
else
{
matrix[index].Add(0, ""); // Key and value here
}

Serially assign values to OrderedDictionary in C#

I have two key-value pairs, and now I want to fill up the larger one with values from the smaller one in a serial manner.
OrderedDictionary pickersPool = new OrderedDictionary(); // Small
OrderedDictionary pickersToTicketMap = new OrderedDictionary(); // Big
pickersPool.Add("emp1", 44);
pickersPool.Add("emp2", 543);
Now I need to update pickersToTicketMap to look like this:
("100", 44);
("109", 543);
("13", 44);
("23", 543);
So basically I need the pickersPool value to cycle through the keys of the pickersToTicketMap dictionary.
I need pickerPool values to keep cycling pickersToTicketMap and updating its value serially.
The pickersToTicketMap orderedlist initially has a value of:
("100", "null");
("109", "null");
("13", "null");
("23", "null");
so I need for the values of PickerPool orderedDictionary to fill up those nulls in a repeated fashion.
It sounds like you should start with a List<string> (or possibly a List<int>, given that they all seem to be integers...) rather than populating your map with empty entries to start with. So something like:
List<string> tickets = new List<string> { "100", "109", "13", "23" };
Then you can populate your pickersToTicketMap as:
var pickers = pickersPool.Values;
var pickerIterator = pickers.GetEnumerator();
foreach (var ticket in tickets)
{
if (!pickerIterator.MoveNext())
{
// Start the next picker...
pickerIterator = pickers.GetEnumerator();
if (!pickerIterator.MoveNext())
{
throw new InvalidOperationException("No pickers available!");
}
}
ticketToPickerMap[ticket] = pickerIterator.Current;
}
Note that I've changed the name from pickersToTicketMap to ticketToPickerMap because that appears to be what you really mean - the key is the ticket, and the value is the picker.
Also note that I'm not disposing of the iterator from pickers. That's generally a bad idea, but in this case I'm assuming that the iterator returned by OrderedDictionary.Values.GetEnumerator() doesn't need disposal.
There may be what you are looking for:
using System.Linq;
...
int i = 0;
// Cast OrderedDictionary to IEnumarable<DictionaryEntry> to be able to use System.Linq
object[] keys = pickersToTicketMap.Cast<DictionaryEntry>().Select(x=>x.Key).ToArray();
IEnumerable<DictionaryEntry> pickersPoolEnumerable = pickersPool.Cast<DictionaryEntry>();
// iterate over all keys (sorted)
foreach (object key in keys)
{
// Set the value of key to element i % pickerPool.Count
// i % pickerPool.Count will return for Count = 2
// 0, 1, 0, 1, 0, ...
pickersToTicketMap[key] = pickersPoolEnumarable
.ElementAt(i % pickersPool.Count).Value;
i++;
}
PS: The ToArray() is required to have a separate copy of the keys, so you don't get a InvalidOperationException due to changing the element you are iterating over.
So you want to update the large dictionary's values with consecutive and repeating values from the possibly smaller one? I have two approaches in mind, one simpler:
You can repeat the smaller collection with Enumerable.Repeat. You have to calculate the count. Then you can use SelectMany to flatten it and ToList to create a collection. Then you can use a for loop to update the larger dictionary with the values in the list via an index:
IEnumerable<int> values = pickersPool.Values.Cast<int>();
if (pickersPool.Count < pickersToTicketMap.Count)
{
// Repeat this collection until it has the same size as the larger collection
values = Enumerable.Repeat( values,
pickersToTicketMap.Count / pickersPool.Count
+ pickersToTicketMap.Count % pickersPool.Count
)
.SelectMany(intColl => intColl);
}
List<int> valueList = values.ToList();
for (int i = 0; i < valueList.Count; i++)
pickersToTicketMap[i] = valueList[i];
I would prefer the above approach, because it's more readable than my second which uses an "infinite" sequence. This is the extension method:
public static IEnumerable<T> RepeatEndless<T>(this IEnumerable<T> sequence)
{
while (true)
foreach (var item in sequence)
yield return item;
}
Now you can use this code to update the larger dictionary's values:
var endlessPickersPool = pickersPool.Cast<DictionaryEntry>().RepeatEndless();
IEnumerator<DictionaryEntry> endlessEnumerator;
IEnumerator<string> ptmKeyEnumerator;
using ((endlessEnumerator = endlessPickersPool.GetEnumerator()) as IDisposable)
using ((ptmKeyEnumerator = pickersToTicketMap.Keys.Cast<string>().ToList().GetEnumerator()) as IDisposable)
{
while (endlessEnumerator.MoveNext() && ptmKeyEnumerator.MoveNext())
{
DictionaryEntry pickersPoolItem = (DictionaryEntry)endlessEnumerator.Current;
pickersToTicketMap[ptmKeyEnumerator.Current] = pickersPoolItem.Value;
}
}
Note that it's important that I use largerDict.Keys.Cast<string>().ToList(), because I can't use the original Keys collection. You get an exception if you change it during enumeration.
Thanks to #jon skeet, although he modified my objects too much while trying to provide a hack for this.
After looking at your solution, I implemented the following, which works well for all my objects.
var pickerIterator = pickerPool.GetEnumerator();
foreach (DictionaryEntry ticket in tickets)
{
if (!pickerIterator.MoveNext())
{
// Start the next picker...
pickerIterator = pickerPool.GetEnumerator();
if (!pickerIterator.MoveNext())
{
throw new InvalidOperationException("No pickers available!");
}
}
ticketToPickerMap[ticket.Key] = pickerIterator.Value.ToString();
}

Arrays/Array Lists

I am fairly new to C#
I am trying to retrieve some information from an external data source and store it in array, once it is in an array I wish to sort it by time.
I know how to do this for just one column in a row, however the information I require has multiple columns.
For example:
foreach (Appointment Appoint in fapts)
{
// Store Appoint.Subject, Appoint.Start, Appoint.Organiser.Name.ToString(), Appoint.Location in an array
}
// Sort my array by Appoint.Start
foreach ( item in myNewArray )
{
//print out Appoint.Subject - Appoint.Start, Appoint.Organiser.Name.ToString() and Appoint.location
}
Many thanks for your help.
EDIT:
I have multiple data sources which pull in this:
foreach (Appointment Appoint in fapts)
{
// Store Appoint.Subject, Appoint.Start, Appoint.Organiser.Name.ToString(), Appoint.Location in an array
}
Hence the need to sort the items in a new array, I know this isn't very efficent but there is no way of getting the information I need in any other way.
You can sort a list using the LINQ sorting operators OrderBy and ThenBy, as shown below.
using System.Linq;
and then...
var appointments = new List<Appointment>();
var sortedAppointments = list.OrderBy(l => l.Subject).ThenBy(l => l.Name).ToList();
This will create a new list of appointments, sorted by subject and then by name.
It's unclear what your final aim is but:
Use a generic List instead of an array:
See this SO question for more information as to why using a List is prefered.
List<Appointment> appointments = new List<Appointment>();
foreach (Appointment Appoint in fapts)
{
appointments.Add(Appoint);
}
foreach (var item in appointments)
{
Console.WriteLine(item.Subject);
Console.WriteLine(item.Foo);
// Here you could override ToString() on Appointment to print eveything in one Console.WriteLine
}
If the aim of your code is to order by time, try the following:
var sortedAppointments = fapts.OrderBy(a => a.Start); // assuming Start is a DateTime property of `Appointment`.
Consider a Dictionary Object instead of an array if the data is conceptually one row multiple columns.
foreach(KeyValuePair<string, string> entry in MyDic)
{
// do something with entry.Value or entry.Key
}
You already have a list of objects in fpts, sort that list itself:
fpts.OrderBy(x => x.Subject).ThenBy(x => x.Location).ToList();
LINQ is your friend here.
fapts appears to already be a collection so you could just operate on it.
var myNewArray = fapts.OrderBy(Appoint => Appoint.Start).ToArray()
I've used the ToArray() call to force immediate evaluation and means that myNewArray is already sorted so that if you use it more than once you don't have to re-evaluate the sort.
Alternatively if you are only using this once you can just as easily miss the ToArray() portion out and then execution of the sort will be deferred until you try and enumerate through myNewArray.
This solution puts the source objects into the array, but if you are just wanting to store the specific fields you mention then you will need to use a select. You have two choices for the array item type, you can either use an anonymous class which provides difficulties if you are returning this array from a function or define a class.
For anonymous:
var myNewArray = fapts.OrderBy(Appoint => Appoint.Start)
.Select(Appoint => new {
Start = Appoint.Start,
Organiser = Appoint.Organiser.Name.ToString(),
Location = Appoint.Location
}).ToArray();
For named class assuming class is MyClass:
var myNewArray = fapts.OrderBy(Appoint => Appoint.Start)
.Select(Appoint => new MyClass {
Start = Appoint.Start,
Organiser = Appoint.Organiser.Name.ToString(),
Location = Appoint.Location
}).ToArray();
You have a wide range of options. The 2 most common are:
1) Create a class, then define an array or list of that class, and populate that
2) Create a structure that matches the data format and create an array or list of that
Of course, you could put the data into an XML format or dataset, but that's probably more work than you need.
public List<foo> appointments = new List<foo>();
public struct foo
{
public string subject ;
public DateTime start ;
public string name ;
public string location ;
}
public void foo1()
{
// parse the file
while (!File.eof())
{
// Read the next line...
var myRecord = new foo() ;
myRecord.subject = data.subject ;
myRecord.start = data.Start ;
myRecord.name = data.Name ;
//...
appointments.Add(myRecord);
}
}
Enjoy
(Since I can't comment and reply to the comment - it wasn't clear if he had a class, etc. or was just showing us what he wanted to do. I assumed it was just for demonstration purposes since there wasn't any info as to how the data was being read. If he could already put it into a class, than the first answer applied anyway. I just tossed the last 2 in there because they were options for getting the data first.)

Iterating over a growing dictionary

I am working with C# and I have a dictionary called intervalRecordsPerObject of type Dictionary<string, List<TimeInterval>>. I need to iterate through the dictionary. The problem is: everytime I iterate through the dictionary, more KeyValuePairs may get added to it. As the dictionary grows, I need to keep iterating over the new entries too.
Firstly, I did this: A simple foreach loop that gave me an InvalidOperationException saying
Collection was modified; enumeration operation may not execute.
I know I cannot iterate over the Dictionary this way if it keeps changing as C# converts it with ToList() before foreach loop.
I know I can copy the keys to a temporary array, iterate over the dictionary using simple for loop and Count and whenever a new entry is added to the dictionary, add the corresponding key to the array too. Now, the problem is a simple array cannot grow dynamically and I don't know beforehand what the required size could be.
To move ahead, I thought I'd do this:
List<string> keyList = new List<string>(intervalRecordsPerObject.Count);
intervalRecordsPerObject.Keys.CopyTo(keyList.ToArray(), 0);
I cannot do this either. keyList is currently empty and therefore keyList.toArray() returns an array of length 0 which gives me an ArgumentException saying
Destination array is not long enough to copy all the items in the
collection. Check array index and length.
I am stuck! Any idea what more can I try? Thanks for any help.
Addition 1:
The dictionary stores the time intervals for which a particular object is present. Key is the ID of the object. New entries may get added in every iteration (worst case) or may not get added even once. Whether or not entries are added is decided by a few conditions (whether the object overlaps with some other intervals, etc.). This triggers a change in the ID and the corresponding interval list which is then added as a new entry to the dictionary.
Something like this:
List<string> keys = dict.Keys.ToList();
for (int i = 0; i < keys.Count; i++)
{
var key = keys[i];
List<TimeInterval> value;
if (!dict.TryGetValue(key, out value))
{
continue;
}
dict.Add("NewKey", yourValue);
keys.Add("NewKey");
}
The trick here is that you enumerate the List<T> by index! In this way, even if you add new elements, the for (...) will "catch" them.
Other possible solution, by using a temporary Dictionary<,>:
// The main dictionary
var dict = new Dictionary<string, List<TimeInterval>>();
// The temporary dictionary where new keys are added
var next = new Dictionary<string, List<TimeInterval>>();
// current will contain dict or the various instances of next
// (multiple new Dictionary<string, List<TimeInterval>>(); can
// be created)
var current = dict;
while (true)
{
foreach (var kv in current)
{
// if necessary
List<TimeInterval> value = null;
// We add items only to next, that will be processed
// in the next while (true) cycle
next.Add("NewKey", value);
}
if (next.Count == 0)
{
// Nothing was added in this cycle, we have finished
break;
}
foreach (var kv in next)
{
dict.Add(kv.Key, kv.Value);
}
current = next;
next = new Dictionary<string, List<TimeInterval>>();
}
You can access the Keys by positions rather than by content and use a normal For loop (allowing additions/removals without any restriction).
for (int i = 0; i < dict.Keys.Count; i++)
{
string curKey = dict.Keys.ElementAt(i);
TimeInterval curVal = dict.Values.ElementAt(i);
//TimeInterval curVal = dict[curKey];
//Can add or remove entries
}

Check that all values of an array have been used

Sorry if this is a stupid noob question. I'm doing a very small project for my girlfriend - a list of countries and she has to enter their capitals (obscure countries, mind you) . Since I'm a total beginner, I had to resort to using two arrays, one for countries and the other for capitals, with matching indexes. That way it's easy to check for the right answer and I don't have to parse any text files or use any data-bases. I'm using random numbers to make it more interesting. To stop the program from generating the same countries over and over again, I'm using a List of integers that keeps tracks of what indexes have already been used and regenerates the number if the list contains the previous one. Pretty basic stuff. Surprisingly, it all works.
But I'm having a problem. How do I check that I've run out of countries, basically? :) I can't simply check the List size against my countries array, since List probably includes more values than the array, and if (taken.Equals(Countries.Length)) doesn't seem to work. Or I can't find the right place in the code to put this check.
Sorry if this is simple, but I can't seem to find a proper solution.
EDIT
Wow, what an amazing community. During the short walk from Starbucks to my place I get dozens of quality answers which cover a huge array of design techniques. This is so great! Thank you everyone! Obviously, the question has been answered but I will post the code for you, if anyone has any additional comments.
// JUST A TEST FOR NOW, 13 COUNTRIES
string[] Countries = {"Belgium", "France", "The Netherlands", "Spain", "Monaco", "Belarus", "Germany",
"Portugal", "Ukraine", "Russia", "Sweden", "Denmark", "South Africa"};
string[] Capitals = {"Brussels", "Paris", "Amsterdam", "Madrid", "Monaco", "Minsk", "Berlin",
"Lisbon", "Kiev", "Moscow", "Stockholm", "Copenhagen", "Pretoria"};
Random number = new Random();
List<int> taken = new List<int>();
int index;
int score = 0;
private int Generate()
{
while (true) {
index = number.Next(0, Countries.Length);
if (taken.Contains(index)) continue;
// THIS IS WHAT I WAS INITIALLY TRYING TO DO
if (taken.Equals(Countries.Length)) {
MessageBox.Show("Game over!");
return -1;
}
return index;
}
}
private void Form1_Load(object sender, EventArgs e)
{
index = Generate();
taken.Add(index);
label1.Text = Countries[index];
label3.Text = "0 out of " + Countries.Length.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text.Trim() == Capitals[index].ToString()) {
label2.Text = "You win!";
index = Generate();
taken.Add(index);
label1.Text = Countries[index];
textBox1.Clear();
label3.Text = ++score + " out of " + Countries.Length.ToString();
}
else {
label2.Text = "Wrong!";
textBox1.Clear();
}
}
}
}
To stop the program from generating the same countries over and over again, I'm using a List of integers that keeps tracks of what indexes have already been used and regenerates the number if the list contains the previous one.
...
How do I check that I've run out of countries, basically?
You might want to consider an alternative approach, as this is going to be quite expensive and overly complicated.
Instead of trying to add one country at random, checking against ones you've already added, you could just make the entire list of countries, then perform a shuffle ("random sort") on the collection. This way, you'll get all of the countries in one shot in a random order.
Instead of using two arrays, or an array and a list, let's introduce something of C# 4.0 that actually looks and is easy to use and seems to be made for this type of assignments.
Follow this code with your eyes and specifically look how these "anonymous types" are used in the end. It makes life real easy.
// initialize your array like so,
// now you can access your items as countries[1].name and countries[1].city
// and you will never have to worry about having too much cities or countries
// PLUS: they're always together!
var countries = new [] {
new { name = "The Netherlands", city = "Amsterdam"},
new { name = "Andorra", city = "Vaduz" },
new { name = "Madagascar", city = "Antananarivo"}
};
// randomize by shuffling (see http://stackoverflow.com/questions/375351/most-efficient-way-to-randomly-sort-shuffle-a-list-of-integers-in-c-sharp/375446#375446)
Random random = new Random();
for (int i = 0; i < countries.Length; i += 1)
{
int swapIndex = random.Next(i, countries.Length);
if (swapIndex != i)
{
var temp = countries[i];
countries[i] = countries[swapIndex];
countries[swapIndex] = temp;
}
}
// go through all your items in the array using foreach
// so you don't have to worry about having too much items
foreach(var item in countries)
{
// show your girlfriend the country, something like
string inputString = DisplayCountry(item.country);
if(inputString == item.city)
{
ShowMessage("we are happy, you guessed right!");
}
}
// at the end of the foreach-loop you've automatically run out of countries
DisplayScore(to-your-girlfriend);
Note: you can easily expand on this anonymous types by adding whether or not that particular country/city pair was guessed right and make a subsequent test with the ones she failed.
You could use a HashSet<int> to keep track of indexes that have been used. This won't accept duplicate values. The Add method returns a boolean that indicates whether the value was already in the list:
if (hashSet.Add(index))
DisplayValue(index);
else
//regenerate
But I would probably use your existing stragegy, but backwards: create a list pre-filled with values from 0 to Count - 1. Pick indexes from this list, removing them as you use them. This is logically similar to Reed Copsey's suggestion of sorting, but probably requires less change to your existing code.
var availableIndexes = new List<int>(Enumerable.Range(0, countryCount));
var random = new Random();
while (availableIndexes.Count > 0)
{
var index = availableIndexes[Random.Next(0, availableIndexes.Count)];
DisplayValue(index);
availableIndexes.Remove(index);
}
You can use a key/value pair, like a Dictionary<string, string> to store your countries and capitals. Then iterate through the collection using a random LINQ orderby clause:
Dictionary<string, string> Countries = new Dictionary<int, string>();
// populate your collection of countries
foreach(var country in Countries.OrderBy(c => Guid.NewGuid()))
{
Console.WriteLine("Key: {0} Value: {1}", country.Key, country.Value);
}
Create a Country class and a Capital class.
Then model your classes to use a Dictionary<TKey, TValue> Generic Collection so that you declare the generic Dictionary object as:
Dictionary<Country, Capital>
where Country is the key and Capital is its value.
For MSDN reference to Dictionary and its sample usage, you can follow below link:
http://msdn.microsoft.com/en-us/library/xfhwa508.aspx
As you keep using Countries and Capitals, add them to above Dictionary instance after checking for their existence in the Dictionary instance, if any of them do exist then either popup an info message or a warning.
Quick and dirty, not necessarily efficient or secure.
Dictionary<string, string> countriesAndCapitals = new Dictionary<string, string>()
{
{ "Afghanistan", "Kabul" },
{ "Albania", "Tirane" },
{ "Algeria","Algers" },
{ "Andorra", "Andorra la Vella" } //etc, etc
};
foreach (var countryCapital in countriesAndCapitals.OrderBy(f => Guid.NewGuid()))
{
Console.WriteLine(countryCapital.Key + " " + countryCapital.Value);
}
It seems like what you need is a different type of data structure, two sets of lists would work fine but it is complicated for nothing. I suggest looking into the dictionary list type.
Dictionary<string,string> countryList = new Dictionary<string,string>();
countryList.Add("Canada","Ottawa");
countryList.Add("Thailand","Bankok");
etc...
You could then iterate through the list while a boolean value sees whether or not there was a hit. More info on Dictionary list type.
Why don't you remove the items from the list that you used? Then you don't have conflicts. Then you check states.Count() > 0.
The quickest thing I can think to do is to use the Distinct() call on your list. Then your count of items in the list can be compared to your array's count to see if all have been used.
if(myUsedList.Distinct().Count() < myArray.Count) { ... }

Categories